使用新输入系统处理不同的函数调用
Handling different functions calls using New Input System
我是 Unity 新输入系统的新手,我最近将我的项目从旧输入系统迁移到新输入系统,但我在使用它时遇到了一些困难。
我有一个名为 InputManager
的 class 管理我游戏的所有输入操作,还有另一个名为 PlayerInteractions
的 class 用于保存所有玩家的交互,例如如拾取物品、打开和关闭drawers/doors等。
playerInteraction
class 在使用旧输入系统时工作得很好,但是当我将其更改为新输入系统时,我无法正确处理函数调用,因此它无法完全工作.我设法使拾取对象工作,但 opening/closing 部分没有工作,因为为此我从一个名为 InteractiveObjects
的 class 调用另一个函数,该函数附加到所有可以是 opened/closed 例如 door/drawers...
我很难处理这些函数调用,因为我在新输入系统方面不够好。
这是 PlayerInteractions Class
的片段
private InteractiveObjects interactiveObjects;
bool PickingUp, Open;
void Update()
{
raycastPos = mainCamera.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hit;
if (Physics.SphereCast(raycastPos, sphereCastRadius, mainCamera.transform.forward, out hit, maxDistance, 1 << interactableLayerIndex))
{
lookObject = hit.collider.transform.gameObject;
}
else
{
lookObject=null;
}
if (PickingUp)
{
if (currentlyPickedUpObject == null)
{
if (lookObject != null)
{
PickupObject();
}
}
else
{
BreakConnection();
}
}
PickingUp = false;
if (hit.transform)
{
interactiveObjects = hit.transform.GetComponent<InteractiveObjects>();
}
else
{
lookObject = null;
interactiveObjects = null;
}
if (Open)
{
if (interactiveObjects)
{
interactiveObjects.PerformAction();
}
}
Open = false;
}
public void OnPickingUp()
{
PickingUp = true;
}
public void OnOpen()
{
Open = true;
}
上面这部分:
if (Open)
{
if (interactiveObjects)
{
interactiveObjects.PerformAction();
}
}
是这样的:
if (Input.GetKeyDown(KeyCode.E))
{
if (interactiveObjects)
{
interactiveObjects.PerformAction();
}
}
InteractiveObject
class 是这样的:
public void PerformAction()
{
if (aSource)
{
aSource.Play();
}
if (Input.GetKeyDown(KeyCode.E))
{
if (isOpen)
{
iTweenArgs["position"] = closedPosition;
iTweenArgs["rotation"] = closedPosition;
}
else
{
iTweenArgs["position"] = openPosition;
iTweenArgs["rotation"] = openPosition;
}
isOpen = !isOpen;
switch(movementType)
{
case MovementType.Slide:
iTween.MoveTo(gameObject, iTweenArgs);
break;
case MovementType.Rotate:
iTween.RotateTo(gameObject, iTweenArgs);
break;
}
}
if(Input.GetKeyDown(KeyCode.E))
已更改为 if (Open)
。
这里是完整的 IneractiveObject
class 更改后:
public class InteractiveObjects : MonoBehaviour
{
[SerializeField] private Vector3 openPosition, closedPosition;
[SerializeField] private float animationTime;
[SerializeField] private bool isOpen = false;
[SerializeField] private MovementType movementType;
bool Open;
private enum MovementType { Slide, Rotate };
private Hashtable iTweenArgs;
private AudioSource aSource;
void Start()
{
iTweenArgs = iTween.Hash();
iTweenArgs.Add("position", openPosition);
iTweenArgs.Add("time", animationTime);
iTweenArgs.Add("islocal", true);
aSource = GetComponent<AudioSource>();
}
public void PerformAction()
{
if (aSource)
{
aSource.Play();
}
if (Open)
{
if (isOpen)
{
iTweenArgs["position"] = closedPosition;
iTweenArgs["rotation"] = closedPosition;
}
else
{
iTweenArgs["position"] = openPosition;
iTweenArgs["rotation"] = openPosition;
}
isOpen = !isOpen;
switch (movementType)
{
case MovementType.Slide:
iTween.MoveTo(gameObject, iTweenArgs);
break;
case MovementType.Rotate:
iTween.RotateTo(gameObject, iTweenArgs);
break;
}
}
Open = false;
}
public void OnOpen()
{
Open = true;
}
}
这是我的输入操作:
InputManager
class:
public class InputManager : MonoBehaviour
{
[SerializeField] Movement movement;
[SerializeField] PlayerInteractions playerInteractions;
[SerializeField] MouseLook mouseLook;
PlayerControls controls;
PlayerControls.GroundMovementActions groundMovement;
Vector2 horizontalInput;
Vector2 mouseInput;
private void Awake()
{
controls = new PlayerControls();
groundMovement = controls.GroundMovement;
// groundMovement.[action].performed += context => do something
groundMovement.HorizontalMovement.performed += ctx => horizontalInput = ctx.ReadValue<Vector2>();
groundMovement.Jump.performed += _ => movement.OnJumpPressed();
groundMovement.Running.performed += _ => movement.OnRunning();
groundMovement.PickingUp.performed += _ => playerInteractions.OnPickingUp();
groundMovement.MouseX.performed += ctx => mouseInput.x = ctx.ReadValue<float>();
groundMovement.MouseY.performed += ctx => mouseInput.y = ctx.ReadValue<float>();
groundMovement.Open.performed += _ => playerInteractions.OnOpen();
}
private void Update()
{
movement.ReceiveInput(horizontalInput);
mouseLook.ReceiveInput(mouseInput);
}
private void OnEnable()
{
controls.Enable();
}
private void OnDestroy()
{
controls.Disable();
}
}
所以 InputManager
class 从 playerInteractions
调用一个函数,它也从 InteractiveObjects
调用一个函数以实现 opening/closing 功能。这对我不起作用,但我不知道如何解决这个问题。请帮助。
解决方案在这里,您不再需要Open
布尔值,您可以通过新的输入系统直接调用函数。为了这份工作;仅输入 if on OnOpen
.
的内容
public void OnOpen()
{
if (isOpen)
{
iTweenArgs["position"] = closedPosition;
iTweenArgs["rotation"] = closedPosition;
}
else
{
iTweenArgs["position"] = openPosition;
iTweenArgs["rotation"] = openPosition;
}
isOpen = !isOpen;
switch(movementType)
{
case MovementType.Slide:
iTween.MoveTo(gameObject, iTweenArgs);
break;
case MovementType.Rotate:
iTween.RotateTo(gameObject, iTweenArgs);
break;
}
}
这不仅简化了代码的结构。相反,它可以防止 if 条件在更新中重复出现。现在 运行 OnOpen
按 B 键设置:
controls.GroundMovement.Open.performed += _ => playerInteraction.OnOpen();
条件如何连续工作?
有多种方法可以构建连续工作的函数。这是一个通过在目标对象脚本中定义 Func<bool>
来工作的示例:
public class PlayerInteraction : MonoBehaviour
{
public Func<bool> IsPressingOpen;
public void Update()
{
if (IsPressingOpen())
{
// do something...
}
}
}
并且根据key pressing
的结果设置函数即可:
playerInteraction.IsPressingOpen = () => controls.GroundMovement.Open.IsPressed();
希望这个回答全面实用。
我是 Unity 新输入系统的新手,我最近将我的项目从旧输入系统迁移到新输入系统,但我在使用它时遇到了一些困难。
我有一个名为 InputManager
的 class 管理我游戏的所有输入操作,还有另一个名为 PlayerInteractions
的 class 用于保存所有玩家的交互,例如如拾取物品、打开和关闭drawers/doors等。
playerInteraction
class 在使用旧输入系统时工作得很好,但是当我将其更改为新输入系统时,我无法正确处理函数调用,因此它无法完全工作.我设法使拾取对象工作,但 opening/closing 部分没有工作,因为为此我从一个名为 InteractiveObjects
的 class 调用另一个函数,该函数附加到所有可以是 opened/closed 例如 door/drawers...
我很难处理这些函数调用,因为我在新输入系统方面不够好。
这是 PlayerInteractions Class
private InteractiveObjects interactiveObjects;
bool PickingUp, Open;
void Update()
{
raycastPos = mainCamera.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hit;
if (Physics.SphereCast(raycastPos, sphereCastRadius, mainCamera.transform.forward, out hit, maxDistance, 1 << interactableLayerIndex))
{
lookObject = hit.collider.transform.gameObject;
}
else
{
lookObject=null;
}
if (PickingUp)
{
if (currentlyPickedUpObject == null)
{
if (lookObject != null)
{
PickupObject();
}
}
else
{
BreakConnection();
}
}
PickingUp = false;
if (hit.transform)
{
interactiveObjects = hit.transform.GetComponent<InteractiveObjects>();
}
else
{
lookObject = null;
interactiveObjects = null;
}
if (Open)
{
if (interactiveObjects)
{
interactiveObjects.PerformAction();
}
}
Open = false;
}
public void OnPickingUp()
{
PickingUp = true;
}
public void OnOpen()
{
Open = true;
}
上面这部分:
if (Open)
{
if (interactiveObjects)
{
interactiveObjects.PerformAction();
}
}
是这样的:
if (Input.GetKeyDown(KeyCode.E))
{
if (interactiveObjects)
{
interactiveObjects.PerformAction();
}
}
InteractiveObject
class 是这样的:
public void PerformAction()
{
if (aSource)
{
aSource.Play();
}
if (Input.GetKeyDown(KeyCode.E))
{
if (isOpen)
{
iTweenArgs["position"] = closedPosition;
iTweenArgs["rotation"] = closedPosition;
}
else
{
iTweenArgs["position"] = openPosition;
iTweenArgs["rotation"] = openPosition;
}
isOpen = !isOpen;
switch(movementType)
{
case MovementType.Slide:
iTween.MoveTo(gameObject, iTweenArgs);
break;
case MovementType.Rotate:
iTween.RotateTo(gameObject, iTweenArgs);
break;
}
}
if(Input.GetKeyDown(KeyCode.E))
已更改为 if (Open)
。
这里是完整的 IneractiveObject
class 更改后:
public class InteractiveObjects : MonoBehaviour
{
[SerializeField] private Vector3 openPosition, closedPosition;
[SerializeField] private float animationTime;
[SerializeField] private bool isOpen = false;
[SerializeField] private MovementType movementType;
bool Open;
private enum MovementType { Slide, Rotate };
private Hashtable iTweenArgs;
private AudioSource aSource;
void Start()
{
iTweenArgs = iTween.Hash();
iTweenArgs.Add("position", openPosition);
iTweenArgs.Add("time", animationTime);
iTweenArgs.Add("islocal", true);
aSource = GetComponent<AudioSource>();
}
public void PerformAction()
{
if (aSource)
{
aSource.Play();
}
if (Open)
{
if (isOpen)
{
iTweenArgs["position"] = closedPosition;
iTweenArgs["rotation"] = closedPosition;
}
else
{
iTweenArgs["position"] = openPosition;
iTweenArgs["rotation"] = openPosition;
}
isOpen = !isOpen;
switch (movementType)
{
case MovementType.Slide:
iTween.MoveTo(gameObject, iTweenArgs);
break;
case MovementType.Rotate:
iTween.RotateTo(gameObject, iTweenArgs);
break;
}
}
Open = false;
}
public void OnOpen()
{
Open = true;
}
}
这是我的输入操作:
InputManager
class:
public class InputManager : MonoBehaviour
{
[SerializeField] Movement movement;
[SerializeField] PlayerInteractions playerInteractions;
[SerializeField] MouseLook mouseLook;
PlayerControls controls;
PlayerControls.GroundMovementActions groundMovement;
Vector2 horizontalInput;
Vector2 mouseInput;
private void Awake()
{
controls = new PlayerControls();
groundMovement = controls.GroundMovement;
// groundMovement.[action].performed += context => do something
groundMovement.HorizontalMovement.performed += ctx => horizontalInput = ctx.ReadValue<Vector2>();
groundMovement.Jump.performed += _ => movement.OnJumpPressed();
groundMovement.Running.performed += _ => movement.OnRunning();
groundMovement.PickingUp.performed += _ => playerInteractions.OnPickingUp();
groundMovement.MouseX.performed += ctx => mouseInput.x = ctx.ReadValue<float>();
groundMovement.MouseY.performed += ctx => mouseInput.y = ctx.ReadValue<float>();
groundMovement.Open.performed += _ => playerInteractions.OnOpen();
}
private void Update()
{
movement.ReceiveInput(horizontalInput);
mouseLook.ReceiveInput(mouseInput);
}
private void OnEnable()
{
controls.Enable();
}
private void OnDestroy()
{
controls.Disable();
}
}
所以 InputManager
class 从 playerInteractions
调用一个函数,它也从 InteractiveObjects
调用一个函数以实现 opening/closing 功能。这对我不起作用,但我不知道如何解决这个问题。请帮助。
解决方案在这里,您不再需要Open
布尔值,您可以通过新的输入系统直接调用函数。为了这份工作;仅输入 if on OnOpen
.
public void OnOpen()
{
if (isOpen)
{
iTweenArgs["position"] = closedPosition;
iTweenArgs["rotation"] = closedPosition;
}
else
{
iTweenArgs["position"] = openPosition;
iTweenArgs["rotation"] = openPosition;
}
isOpen = !isOpen;
switch(movementType)
{
case MovementType.Slide:
iTween.MoveTo(gameObject, iTweenArgs);
break;
case MovementType.Rotate:
iTween.RotateTo(gameObject, iTweenArgs);
break;
}
}
这不仅简化了代码的结构。相反,它可以防止 if 条件在更新中重复出现。现在 运行 OnOpen
按 B 键设置:
controls.GroundMovement.Open.performed += _ => playerInteraction.OnOpen();
条件如何连续工作?
有多种方法可以构建连续工作的函数。这是一个通过在目标对象脚本中定义 Func<bool>
来工作的示例:
public class PlayerInteraction : MonoBehaviour
{
public Func<bool> IsPressingOpen;
public void Update()
{
if (IsPressingOpen())
{
// do something...
}
}
}
并且根据key pressing
的结果设置函数即可:
playerInteraction.IsPressingOpen = () => controls.GroundMovement.Open.IsPressed();
希望这个回答全面实用。