扳机并不能阻止敌人行走

问题描述 投票:0回答:2

我在使用 Unity 制作的游戏中遇到了灯光系统问题,我试图在敌人触摸玩家发出的灯光时阻止敌人,但是当他触摸灯光时,enterTrigger 和 exitTrigger 函数是同时调用多次。我认为这可能是由我在更新方法中处理光线的方式引起的。

玩家脚本

public class Player : MonoBehaviour
{
 #region Light
 [Header("Light Settings")]
 private bool lightOn;
 public GameObject lightUp;
 public GameObject lightDown;
 public GameObject lightLeft;
 public GameObject lightRight;
 #endregion

 void Start()
 {
     rb2D = GetComponent<Rigidbody2D>();
 }

 void Update()
 {
     batterySystem.UpdateBatteryUI();
     if (canMove)
     {
         HandleMovement();
         HandleLantern();
         batterySystem.HandleBatteryUsage(lightOn);
         if (Input.GetKey(KeyCode.Q))
         {
             batterySystem.HandleBatteryRecharge();
         }
         if (Input.GetKeyUp(KeyCode.Q))
         {
             batterySystem.CancelRecharge();
         }
     }
 }
 #region Light Methods
 public void HandleLantern()
 {
     if (Input.GetKeyDown(KeyCode.R) && batterySystem.batteryCount > 0)
     {
         lightOn = !lightOn;

         anim.SetBool("Light", lightOn);

         if (lightOn)
         {
             UpdateLightDirection(lastMove);
         }
         else
         {
            
             DisableAllLights();
         }
     }
 }

 private void UpdateLightDirection(Vector2 direction)
 {
     DisableAllLights();

     if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y))
     {
         if (direction.x > 0)
         {
             lightRight.SetActive(true);
         }
         else if (direction.x < 0)
         {
             lightLeft.SetActive(true);
         }
     }
     else
     {
         if (direction.y > 0)
         {
             lightUp.SetActive(true);
         }
         else if (direction.y < 0)
         {
             lightDown.SetActive(true);
         }
     }
 }

 private void DisableAllLights()
 {
     lightUp.SetActive(false);
     lightDown.SetActive(false);
     lightLeft.SetActive(false);
     lightRight.SetActive(false);
 }


 public void TurnOffLight()
 {
     lightOn = false;
     anim.SetBool("Light", false);
     DisableAllLights(); 
 }
 #endregion

}

敌人脚本

public class FollowEnemy : MonoBehaviour
{
    public float speed;
    public float defaultSpeed; 
    private float distance;
    public float minimumDistance;
    public float attackDistance;

    public bool canMove = true;

    void Start()
    {
        defaultSpeed = speed; 
    }

    void Update()
    {
            Walk();               
    }

    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Light"))
        {
            canMove = false;
            speed = 0f;
            Debug.Log("Entered Light Trigger");
        }
    }

    private void OnTriggerExit2D(Collider2D other)
    {
        if (other.CompareTag("Light"))
        {
            canMove = true;
            speed = defaultSpeed;
            Debug.Log("Exited Light Trigger");
        }
    }

    private void Walk()
    {
        if (canMove)
        { 
            distance = Vector2.Distance(transform.position, GameObject.FindGameObjectWithTag("Player").transform.position);

            Vector2 direction = GameObject.FindGameObjectWithTag("Player").transform.position - transform.position;
            direction.Normalize();
            float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;

            if (distance < minimumDistance)
            {
                transform.position = Vector2.MoveTowards(this.transform.position, GameObject.FindGameObjectWithTag("Player").transform.position, speed * Time.deltaTime);
                transform.rotation = Quaternion.Euler(Vector3.forward * angle);
            }
            if (distance < attackDistance)
            {
                speed = 0;
            }
        }
    }
}

我也尝试禁用触发器,但它不起作用,EnterTrigger2D和ExitTrigger2d不断被调用很多次。

c# unity-game-engine 2d topdown
2个回答
0
投票

这很可能是由两个问题引起的:

使用
Update
代替
FixedUpdate

在Unity中,物理系统并不是每帧都运行。相反,它以固定的时间步长运行。因此,Unity 为您提供了另一种与物理系统相关的 Update 方法:

FixedUpdate
FixedUpdate
每当您的代码依赖或修改物理系统时就可以使用,否则,您的物理将取决于您的帧速率。

Update
更改为
FixedUpdate
内的
FollowEnemy
,因为你的
Walk()
方法会移动你的敌人(这是与物理相关的,因为
OnTrigger
回调)。

void FixedUpdate()
{
    Walk();
}

直接修改刚体的变换

Walk()
做了另一件会扰乱物理系统的事情:直接修改它的
transform
。虽然它看起来有效,但敌人会在被弹出之前暂时移动到墙壁内时对着墙壁抖动,并且触发回调可能会表现得很奇怪。

要解决此问题,请保留对敌人的

Rigidbody2D
的引用并更改
velocity
,而不是
transform.position

public class FollowEnemy : MonoBehaviour
{
    // Add and assign within Unity's Inspector:
    public Rigidbody2D rigidbody;

    // The rest of your variables here...

    // Your other functions here...
 
    private void Walk()
    {
        if (canMove)
        { 
            distance = Vector2.Distance(transform.position, GameObject.FindGameObjectWithTag("Player").transform.position);

            Vector2 direction = GameObject.FindGameObjectWithTag("Player").transform.position - transform.position;
            direction.Normalize();
            float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;

            if (distance < minimumDistance)
            {
                rigidbody.velocity = direction * speed;
                rigidbody.rotation = Quaternion.Euler(Vector3.forward * angle);
            }
            else
            {
                rigidbody.velocity = Vector2.zero;
            }
            if (distance < attackDistance)
            {
                speed = 0;
            }
        }
    }
}

0
投票

当您禁用灯光游戏对象时,如果灯光碰撞器位于触发器内部,则会调用 OnTriggerExit。
这是因为碰撞体不再位于触发碰撞体内部。
当退出被呼叫时,你允许敌人再次移动。

您需要更改游戏中的交互方式才能解决问题。

一种方法是切换灯光组件而不是整个对象。 这需要在实现其他逻辑时检查灯是否打开或关闭。

© www.soinside.com 2019 - 2024. All rights reserved.