Unity角色行走开发遇CS1061错误:PlayerInput无CharacterControls定义
error CS1061: 'PlayerInput' does not contain a definition for 'CharacterControls' and no accessible extension method 'CharacterControls' accepting a first argument of type 'PlayerInput' could be found (are you missing a using directive or an assembly reference?)
我在Unity中实现角色行走功能时碰到上述错误,刚接触C#找不到可行的解决办法,附上我的代码:
using UnityEngine; using UnityEngine.InputSystem; using System.Collections; using System.Collections.Generic; using static System.Numerics.Vector3; class AnimationAndMovementController : MonoBehaviour { PlayerInput playerInput; CharacterController characterController; Animator animator; Vector2 currentMovementInput; Vector3 currentMovement; bool isMovementPressed; float rotationFactorPerFrame = 15.0f; public bool IsMovementPressed { get => isMovementPressed; set => isMovementPressed = value; } void Awake() { playerInput = new PlayerInput(); characterController = GetComponent<CharacterController>(); animator = GetComponent<Animator>(); playerInput.CharacterControls.Move.started += onMovementInput; playerInput.CharacterControls.Move.canceled += onMovementInput; playerInput.CharacterControls.Move.performed += onMovementInput; } void handleRotation() { Vector3 posititonToLookAt; posititonToLookAt.z = currentMovement.z; posititonToLookAt.y = 0.0f; posititonToLookAt.x = currentMovement.x; Quaternion currentRotation = transform.rotation; if (IsMovementPressed) { Quaternion targetRotation = Quaternion.LookRotation(posititonToLookAt); transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactorPerFrame * Time.deltaTime); } } void onMovementInput (InputAction.CallbackContext context) { currentMovementInput = context.ReadValue<Vector2>(); currentMovement.x = currentMovementInput.x; currentMovement.z = currentMovementInput.y; IsMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0; } void handleAnimation() { bool isWalking = animator.GetBool("isWalking"); if (IsMovementPressed & !isWalking) { animator.SetBool("isWalking", true); } else if (!IsMovementPressed & isWalking) { animator.SetBool("isWalking", false); } } // Update is called once per frame void Update() { handleRotation(); handleAnimation(); characterController.Move(currentMovement * Time.deltaTime); } void OnEnable() { playerInput.CharacterControls.Enable(); } void OnDisable() { playerInput.CharacterControls.Disable(); } }
错误原因及解决办法
核心问题:你代码中使用的
PlayerInput是Unity内置的输入系统类,但CharacterControls是通过输入动作资产生成的自定义类,两者不是同一个东西。内置PlayerInput没有CharacterControls这个成员,所以报错。步骤1:生成正确的输入动作类
- 打开你创建的
.inputactions资产文件 - 在Inspector面板里勾选「Generate C# Class」选项
- 确认「Class Name」的名称(比如你的输入资产叫
CharacterControls,生成的类名就是这个;如果叫PlayerControls,类名就是PlayerControls) - 点击「Apply」按钮生成对应的C#类文件
- 打开你创建的
步骤2:修正代码中的类型引用
把代码里的PlayerInput playerInput;替换成你生成的类名,比如如果生成的类是CharacterControls,就改成:CharacterControls playerInput;同时Awake方法里的实例化也要对应修改:
playerInput = new CharacterControls();额外问题修正
代码里的using static System.Numerics.Vector3;是错误的,这个是.NET框架的Vector3,不是Unity引擎的UnityEngine.Vector3,会导致旋转逻辑出错,直接删掉这个using语句即可。另外逻辑判断里的&建议改成&&(逻辑与),&是按位与,适合逻辑判断的是&&。
修正后的完整代码示例
using UnityEngine; using UnityEngine.InputSystem; using System.Collections; using System.Collections.Generic; class AnimationAndMovementController : MonoBehaviour { // 替换成你生成的输入动作类名,这里假设是CharacterControls CharacterControls playerInput; CharacterController characterController; Animator animator; Vector2 currentMovementInput; Vector3 currentMovement; bool isMovementPressed; float rotationFactorPerFrame = 15.0f; public bool IsMovementPressed { get => isMovementPressed; set => isMovementPressed = value; } void Awake() { playerInput = new CharacterControls(); characterController = GetComponent<CharacterController>(); animator = GetComponent<Animator>(); playerInput.CharacterControls.Move.started += onMovementInput; playerInput.CharacterControls.Move.canceled += onMovementInput; playerInput.CharacterControls.Move.performed += onMovementInput; } void handleRotation() { Vector3 posititonToLookAt = new Vector3(currentMovement.x, 0.0f, currentMovement.z); Quaternion currentRotation = transform.rotation; if (IsMovementPressed) { Quaternion targetRotation = Quaternion.LookRotation(posititonToLookAt); transform.rotation = Quaternion.Slerp(currentRotation, targetRotation, rotationFactorPerFrame * Time.deltaTime); } } void onMovementInput (InputAction.CallbackContext context) { currentMovementInput = context.ReadValue<Vector2>(); currentMovement.x = currentMovementInput.x; currentMovement.z = currentMovementInput.y; IsMovementPressed = currentMovementInput.x != 0 || currentMovementInput.y != 0; } void handleAnimation() { bool isWalking = animator.GetBool("isWalking"); if (IsMovementPressed && !isWalking) { animator.SetBool("isWalking", true); } else if (!IsMovementPressed && isWalking) { animator.SetBool("isWalking", false); } } void Update() { handleRotation(); handleAnimation(); characterController.Move(currentMovement * Time.deltaTime); } void OnEnable() { playerInput.CharacterControls.Enable(); } void OnDisable() { playerInput.CharacterControls.Disable(); } }
内容的提问来源于stack exchange,提问作者aknee

