方法忽略 class 范围变量值更改
Method ignores class scope variable value change
问题出在布尔值 isDodging
上。它在 Dodge()
方法中设置为 true。这应该触发 Movement()
方法中的 if 语句(在 FixedUpdate()
中调用),但该块总是被跳过。我附上了所有 class' 代码,因为这里一定有我遗漏的东西:
using UnityEngine;
public class MovementController
{
/* COMPONENTS */
public Rigidbody2D Rigidbody { private get; set; }
/* VARIABLES */
private bool isDodging = false;
private Vector2 dodgeDirection = Vector2.right;
private float dodgeDuration = 1f;
private float dodgeSpeed = 20f;
private float timer = 0f;
/* METHODS */
// Called in fixed update (since it's dealing with physics)
public void Movement(Vector2 currentPosition, Vector2 velocity)
{
Debug.Log("In movement: " + isDodging);
if (isDodging)
{
Debug.Log("Dodge 3");
Move(currentPosition, dodgeDirection * dodgeSpeed);
timer += Time.fixedDeltaTime;
if (timer >= dodgeDuration)
{
Debug.Log("Stopped dodging " + Time.fixedTime);
isDodging = false;
}
}
else
{
Move(currentPosition, velocity);
}
}
private void Move(Vector2 currentPosition, Vector2 velocity)
{
if (Rigidbody == null)
{
Debug.LogWarning("No rigidbody to move!");
return;
}
Rigidbody.MovePosition(currentPosition + (velocity * Time.fixedDeltaTime));
}
// Must be called while Movement is being called
public void Dodge(Vector2 direction, float maxSpeed, float speedMultiplier = 2f, float duration = 1f)
{
if (direction == Vector2.zero) { return; }
Debug.Log("Dodge 1 " + isDodging);
dodgeDirection = direction;
dodgeDuration = duration;
dodgeSpeed = maxSpeed * speedMultiplier;
isDodging = true;
Debug.Log("Dodge 2" + isDodging + Time.fixedTime);
timer = 0f;
}
}
事实是,“运动中:”日志始终显示 isDodging 为 false
,并且它下面的 if 块永远不会运行。同时,“Dodge 2”将显示 true
(因为 isDodging
在其正上方发生了变化)。最奇怪的是:“Dodge 1”在第一次调用 Dodge()
时显示 false
,但之后每次调用时都显示 true
- 就好像 isDodging
在class 范围,并且 Movement()
出于某种原因无法识别。
这两个函数都在单独的 MonoBehaviour 中调用:
public class CreatureMovement : MonoBehaviour
{
[Header("Movement")]
[SerializeField] protected Vector2Reference moveDirection;
[SerializeField] protected FloatReference maxSpeed;
[Header("Dodge")]
[SerializeField] private FloatReference dodgeDuration;
[SerializeField] private FloatReference dodgeSpeedMultiplier;
[Header("References")]
[SerializeField] private new Rigidbody2D rigidbody;
private readonly MovementController movement = new MovementController();
public float MaxSpeed { get => maxSpeed; }
private float speed;
private float Speed { get => speed; set => speed = Mathf.Clamp(value, 0, maxSpeed); }
public virtual Vector2 Velocity
{
get => moveDirection.Value * Speed;
set
{
moveDirection.SetValue(value.normalized);
Speed = value.magnitude;
}
}
private void Start() => movement.Rigidbody = rigidbody;
private void FixedUpdate() => movement.Movement(transform.position, Velocity);
public void Dodge() => movement.Dodge(moveDirection, maxSpeed, dodgeSpeedMultiplier, dodgeDuration);
}
其中 Dodge()
从玩家输入调用。
除了闪避之外,移动完全符合预期。问题可能不在 Move()
方法中,因为其中没有 isDodging
。
我完全不知道为什么会这样,代码对我来说似乎很简单,但就是行不通。请帮忙解决这个问题。
您在预制件上调用 Dodge
而不是该预制件的场景实例 运行 CreatureMovement.FixedUpdate
.
我相信您可以通过将此代码放入 Dodge
(来源:Max-Pixel)来验证这一点:
if (gameObject.scene.name == null) Debug.Log("It's a prefab!");
您需要更改输入处理以在场景中的实例而不是预制件上调用 Dodge
。
您可以通过将场景中的实例拖到按钮的 onclick 事件中,然后选择 Dodge
来实现。或者,如果您动态生成对象,您可以在 Start
中找到对按钮的引用,并将 Dodge
添加到它的 onClick
侦听器中:
private void Start()
{
movement.Rigidbody = rigidbody;
// something along the lines of this...
Button buttonRef = GameObject.Find("ButtonName").GetComponent<Button>();
buttonRef.onClick.AddListener(Dodge);
}
问题出在布尔值 isDodging
上。它在 Dodge()
方法中设置为 true。这应该触发 Movement()
方法中的 if 语句(在 FixedUpdate()
中调用),但该块总是被跳过。我附上了所有 class' 代码,因为这里一定有我遗漏的东西:
using UnityEngine;
public class MovementController
{
/* COMPONENTS */
public Rigidbody2D Rigidbody { private get; set; }
/* VARIABLES */
private bool isDodging = false;
private Vector2 dodgeDirection = Vector2.right;
private float dodgeDuration = 1f;
private float dodgeSpeed = 20f;
private float timer = 0f;
/* METHODS */
// Called in fixed update (since it's dealing with physics)
public void Movement(Vector2 currentPosition, Vector2 velocity)
{
Debug.Log("In movement: " + isDodging);
if (isDodging)
{
Debug.Log("Dodge 3");
Move(currentPosition, dodgeDirection * dodgeSpeed);
timer += Time.fixedDeltaTime;
if (timer >= dodgeDuration)
{
Debug.Log("Stopped dodging " + Time.fixedTime);
isDodging = false;
}
}
else
{
Move(currentPosition, velocity);
}
}
private void Move(Vector2 currentPosition, Vector2 velocity)
{
if (Rigidbody == null)
{
Debug.LogWarning("No rigidbody to move!");
return;
}
Rigidbody.MovePosition(currentPosition + (velocity * Time.fixedDeltaTime));
}
// Must be called while Movement is being called
public void Dodge(Vector2 direction, float maxSpeed, float speedMultiplier = 2f, float duration = 1f)
{
if (direction == Vector2.zero) { return; }
Debug.Log("Dodge 1 " + isDodging);
dodgeDirection = direction;
dodgeDuration = duration;
dodgeSpeed = maxSpeed * speedMultiplier;
isDodging = true;
Debug.Log("Dodge 2" + isDodging + Time.fixedTime);
timer = 0f;
}
}
事实是,“运动中:”日志始终显示 isDodging 为 false
,并且它下面的 if 块永远不会运行。同时,“Dodge 2”将显示 true
(因为 isDodging
在其正上方发生了变化)。最奇怪的是:“Dodge 1”在第一次调用 Dodge()
时显示 false
,但之后每次调用时都显示 true
- 就好像 isDodging
在class 范围,并且 Movement()
出于某种原因无法识别。
这两个函数都在单独的 MonoBehaviour 中调用:
public class CreatureMovement : MonoBehaviour
{
[Header("Movement")]
[SerializeField] protected Vector2Reference moveDirection;
[SerializeField] protected FloatReference maxSpeed;
[Header("Dodge")]
[SerializeField] private FloatReference dodgeDuration;
[SerializeField] private FloatReference dodgeSpeedMultiplier;
[Header("References")]
[SerializeField] private new Rigidbody2D rigidbody;
private readonly MovementController movement = new MovementController();
public float MaxSpeed { get => maxSpeed; }
private float speed;
private float Speed { get => speed; set => speed = Mathf.Clamp(value, 0, maxSpeed); }
public virtual Vector2 Velocity
{
get => moveDirection.Value * Speed;
set
{
moveDirection.SetValue(value.normalized);
Speed = value.magnitude;
}
}
private void Start() => movement.Rigidbody = rigidbody;
private void FixedUpdate() => movement.Movement(transform.position, Velocity);
public void Dodge() => movement.Dodge(moveDirection, maxSpeed, dodgeSpeedMultiplier, dodgeDuration);
}
其中 Dodge()
从玩家输入调用。
除了闪避之外,移动完全符合预期。问题可能不在 Move()
方法中,因为其中没有 isDodging
。
我完全不知道为什么会这样,代码对我来说似乎很简单,但就是行不通。请帮忙解决这个问题。
您在预制件上调用 Dodge
而不是该预制件的场景实例 运行 CreatureMovement.FixedUpdate
.
我相信您可以通过将此代码放入 Dodge
(来源:Max-Pixel)来验证这一点:
if (gameObject.scene.name == null) Debug.Log("It's a prefab!");
您需要更改输入处理以在场景中的实例而不是预制件上调用 Dodge
。
您可以通过将场景中的实例拖到按钮的 onclick 事件中,然后选择 Dodge
来实现。或者,如果您动态生成对象,您可以在 Start
中找到对按钮的引用,并将 Dodge
添加到它的 onClick
侦听器中:
private void Start()
{
movement.Rigidbody = rigidbody;
// something along the lines of this...
Button buttonRef = GameObject.Find("ButtonName").GetComponent<Button>();
buttonRef.onClick.AddListener(Dodge);
}