Unity3D关于InputSystem的简单使用(二)

Unity3D关于InputSystem的简单使用(一)

前面提到了关于InputSystem的简单配置 接下来用C#代码的形式用到下面这个接口

public interface IGamePlayActions
{
    void OnMove(InputAction.CallbackContext context);//这里的方法是你添加的具体的Input Action
}

创建Input脚本 并做成ScriptableObject(加不加都行) 并继承接口

并实现抽象接口

//这里的InputMove 指的是你刚才Generate的C#类名
public class PlayerMove : MonoBehaviour, InputMove.IGamePlayActions
{
    public void OnMove(InputAction.CallbackContext context)
    {
        throw new System.NotImplementedException();
    }
}

获取生成类的引用 并实例化

   private InputMove inputActions;
    private void OnEnable()
    {
        inputActions = new InputMove();
        //登记回调函数 这样每次添加新的动作表 在这里登记回调函数
        inputActions.GamePlay.SetCallbacks(this);
    }
    public void DisableAllInputs()
    {
        inputActions.GamePlay.Disable();//禁用动作表
    }
    public void EnableGamePlayInput()
    {
        inputActions.GamePlay.Enable();//启用动作表
    }
    public void OnMove(InputAction.CallbackContext context)
    {
        throw new System.NotImplementedException();
    }

前面我们提到 输入动作是由输入信号触发的事件
声明一个事件onMove

 private event UnityAction<Vector2> onMove = delegate { };
 //因为需要接收的是来自键盘的输入 是一个二维向量 需要添加一个v2的参数

在OnMove函数中调用这个事件:

public void OnMove(InputAction.CallbackContext context)
{
    if (context.phase == InputActionPhase.Performed)//相当于Input.GetKey()
    {
        //传入输入动作读取到的二维向量的值 将其作为参数 
        //当按下按键的时候 调用onmove方法 同时将读取到的二维向量值作为参数
        onMove.Invoke(context.ReadValue<Vector2>());
    }
    if (context.phase == InputActionPhase.Canceled)
    {
        onStopMove.Invoke();
    }
}

关于InputAction

简单了解下

Class InputAction

这个类表示的是一种响应动作逻辑,可以绑定到多个物理输入上,这些绑定的物理输入和得到的输入值将影响同一个 InputAction 对象。该类只代表一种动作“逻辑”而不代表任何物理输入。

每个动作逻辑在每一时刻都有现在的状态阶段(Phase),通过 Enum InputActionPhase 表示,有五种阶段。分别为:Canceled, Disabled, Performed, Started, Waiting。在 Start, Performed, Canceled 阶段会分别触发三个对应的 C# 事件
(类型为eventAction<InputAction.CallbackContext>)。

每次动作逻辑被触发时,可以通过ReadValue()成员来获取本次触发的具体值。

Waiting,Started, Performed,Canceled, Disabled,

Waiting:在动作表启用 且没有输入信号传入
Started:按下按键的那一帧 相当于Input.GetKeyDown()
Performed:输入动作已执行 包含了按下按键和按住按键的两个阶段 相当于Input.Getkey()
Cancel:相当于松开按键的时候 相当于Input.GetKeyUp()

这样 当键盘实现输入后 将具体的vector2的参数传入到事件中 调用事件的函数

在具体的事件函数中写对应的移动代码 就可以实现角色的移动。

参考代码:

[CreateAssetMenu(menuName = "Input")]
public class Input : ScriptableObject, InputSystems.IGamePlayActions
{
    public event UnityAction<Vector2> onMove = delegate { };
    public event UnityAction onStopMove = delegate { };
    private InputSystems inputActions;
    private void OnEnable()
    {
        inputActions = new InputSystems();
        inputActions.GamePlay.SetCallbacks(this);
    }
    private void OnDisable()
    {
        DisableAllInputs();
    }
    public void DisableAllInputs()
    {
        inputActions.GamePlay.Disable();
    }
    public void EnableGamePlayInput()
    {
        inputActions.GamePlay.Enable();
        Cursor.visible = false;
        Cursor.lockState = CursorLockMode.None;
    }
    public void OnMove(InputAction.CallbackContext context)
    {
        if (context.phase == InputActionPhase.Performed)//相当于Input.GetKey()
        {
            //传入输入动作读取到的二维向量的值 将其作为参数 
            //当按下按键的时候 调用onmove方法 同时将读取到的二维向量值作为参数
            onMove.Invoke(context.ReadValue<Vector2>());
        }
        if (context.phase == InputActionPhase.Canceled)
        {
            onStopMove.Invoke();
        }
    }
public class Player : MonoBehaviour
{
    public float moveSpeed = 6f;
    [SerializeField] private Input playerInput;
    [SerializeField] private new Rigidbody2D rigidbody2D;
    [SerializeField] private float acceleTime = 3f;
    [SerializeField] private float deAcceleTime = 3f;
    Coroutine coroutine;
    private void OnEnable()
    {
        //事件处理程序  Player订阅 Input的onMove和onStopMove事件
        playerInput.onMove += Move;
        playerInput.onStopMove += StopMove;
    }
    private void OnDisable()
    {
        playerInput.onMove -= Move;
        playerInput.onStopMove -= StopMove;
    }
    private void Awake()
    {
        rigidbody2D = GetComponent<Rigidbody2D>();
    }
    private void Start()
    {
        playerInput.EnableGamePlayInput();//操作玩家角色时 GamePlay动作表激活 
    }
    private void StopMove()
    {
        if (coroutine != null)
            StopCoroutine(coroutine);//每次按键调用 暂停上一次的协程
        coroutine = StartCoroutine(MoveCoroutine(deAcceleTime, Vector2.zero));
    }

    private void Move(Vector2 moveInput)
    {
        if (coroutine != null)
            StopCoroutine(coroutine);
        coroutine = StartCoroutine(MoveCoroutine(acceleTime, moveInput.normalized * moveSpeed));
    }
    IEnumerator MoveCoroutine(float time, Vector2 moveVelocity)
    {
        float t = 0f;
        while (t < time)
        {
            t += Time.deltaTime / time;
            rigidbody2D.velocity = Vector2.Lerp(rigidbody2D.velocity, moveVelocity, t / time);
            yield return null;
        }
    }
  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 以下是使用Unity3D的最小乘法进行标定的示例代码: ```csharp using UnityEngine; using System.Collections.Generic; public class Calibration : MonoBehaviour { public Camera cameraToCalibrate; public List<Vector3> objectPoints = new List<Vector3>(); public List<Vector2> imagePoints = new List<Vector2>(); private Matrix4x4 cameraMatrix; private Vector4 distortionCoefficients; public void Calibrate() { int pointCount = objectPoints.Count; float[] objectPointsArray = new float[pointCount * 3]; float[] imagePointsArray = new float[pointCount * 2]; for (int i = 0; i < pointCount; i++) { objectPointsArray[i * 3] = objectPoints[i].x; objectPointsArray[i * 3 + 1] = objectPoints[i].y; objectPointsArray[i * 3 + 2] = objectPoints[i].z; imagePointsArray[i * 2] = imagePoints[i].x; imagePointsArray[i * 2 + 1] = imagePoints[i].y; } double[] cameraMatrixArray = new double[9]; double[] distortionCoefficientsArray = new double[4]; double[] rotationVectorsArray = new double[pointCount * 3]; double[] translationVectorsArray = new double[pointCount * 3]; CalibrateCamera(objectPointsArray, imagePointsArray, cameraToCalibrate.pixelWidth, cameraToCalibrate.pixelHeight, cameraMatrixArray, distortionCoefficientsArray, rotationVectorsArray, translationVectorsArray); cameraMatrix.SetRow(0, new Vector4((float)cameraMatrixArray[0], (float)cameraMatrixArray[1], (float)cameraMatrixArray[2], 0f)); cameraMatrix.SetRow(1, new Vector4((float)cameraMatrixArray[3], (float)cameraMatrixArray[4], (float)cameraMatrixArray[5], 0f)); cameraMatrix.SetRow(2, new Vector4((float)cameraMatrixArray[6], (float)cameraMatrixArray[7], (float)cameraMatrixArray[8], 0f)); cameraMatrix.SetRow(3, new Vector4(0f, 0f, 0f, 1f)); distortionCoefficients.Set((float)distortionCoefficientsArray[0], (float)distortionCoefficientsArray[1], (float)distortionCoefficientsArray[2], (float)distortionCoefficientsArray[3]); } [System.Runtime.InteropServices.DllImport("OpenCVForUnity")] private static extern void calib3d_CalibrateCamera_10(System.IntPtr objectPoints, System.IntPtr objectPoints_mat_nativeObj, System.IntPtr imagePoints, System.IntPtr imagePoints_mat_nativeObj, int width, int height, System.IntPtr cameraMatrix, System.IntPtr cameraMatrix_mat_nativeObj, System.IntPtr distCoeffs, System.IntPtr distCoeffs_mat_nativeObj, System.IntPtr rvecs, System.IntPtr rvecs_mat_nativeObj, System.IntPtr tvecs, System.IntPtr tvecs_mat_nativeObj); private static void CalibrateCamera(float[] objectPointsArray, float[] imagePointsArray, int width, int height, double[] cameraMatrixArray, double[] distortionCoefficientsArray, double[] rotationVectorsArray, double[] translationVectorsArray) { System.IntPtr objectPoints = new System.IntPtr(); System.IntPtr imagePoints = new System.IntPtr(); System.IntPtr cameraMatrix = new System.IntPtr(); System.IntPtr distCoeffs = new System.IntPtr(); System.IntPtr rvecs = new System.IntPtr(); System.IntPtr tvecs = new System.IntPtr(); using (var objectPoints_mat = new MatOfPoint3f()) using (var imagePoints_mat = new MatOfPoint2f()) using (var cameraMatrix_mat = new Mat(3, 3, CvType.CV_64FC1)) using (var distCoeffs_mat = new MatOfDouble()) using (var rvecs_mat = new Mat(pointCount, 3, CvType.CV_64FC1)) using (var tvecs_mat = new Mat(pointCount, 3, CvType.CV_64FC1)) { objectPoints_mat.fromArray(objectPointsArray); objectPoints = objectPoints_mat.nativeObj; imagePoints_mat.fromArray(imagePointsArray); imagePoints = imagePoints_mat.nativeObj; cameraMatrix_mat_array.CopyTo(cameraMatrixArray, 0); cameraMatrix_mat.fromArray(cameraMatrixArray); cameraMatrix = cameraMatrix_mat.nativeObj; distCoeffs_mat_array.CopyTo(distortionCoefficientsArray, 0); distCoeffs_mat.fromArray(distortionCoefficientsArray); distCoeffs = distCoeffs_mat.nativeObj; rvecs_mat.fromArray(rotationVectorsArray); rvecs = rvecs_mat.nativeObj; tvecs_mat.fromArray(translationVectorsArray); tvecs = tvecs_mat.nativeObj; calib3d_CalibrateCamera_10(objectPoints, objectPoints.nativeObj, imagePoints, imagePoints.nativeObj, width, height, cameraMatrix, cameraMatrix.nativeObj, distCoeffs, distCoeffs.nativeObj, rvecs, rvecs.nativeObj, tvecs, tvecs.nativeObj); } } } ``` 注意:此代码需要使用OpenCVForUnity库进行编译。您还需要将 `Calibration` 脚本附加到场景中的一个游戏对象上,并将 `cameraToCalibrate` 和 `objectPoints` 和 `imagePoints` 填充到您的对象和图像点数据。 `Calibrate()` 方法将计算摄像机矩阵和失真系数,并将它们保存在私有变量 `cameraMatrix` 和 `distortionCoefficients` 中。 ### 回答2: 在Unity3D使用最小乘法进行标定的具体代码如下: 1. 首先,创建一个C#脚本,用于实现最小乘法算法的标定方法。例如,将脚本命名为"Calibration.cs"。 2. 在脚本中,定义一个函数,用于进行最小乘法标定。例如,可以定义一个名为"Calibrate()"的函数。 3. 在"Calibrate()"函数中,首先读取需要标定的数据。可以使用Unity提供的输入输出函数,例如使用StreamReader读取文件中的数据,或者使用Input类从输入设备中读取数据。 4. 将读取到的数据保存到数组变量中,以便进行后续计算。 5. 根据最小乘法的原理,计算出标定的参数。这些参数可以是平移、旋转、缩放等,具体根据需求而定。 6. 将计算得到的参数应用到需要标定的对象或场景中,以达到标定的效果。 7. 完成标定后,可以使用Unity的消息系统或者函数回调等方式通知其他部分标定已经完成,可以进行后续操作。 8. 可以根据实际需求对上述步骤进行调整和优化,以适应特定的标定需求。 需要注意的是,最小乘法标定的具体代码实现可以根据具体的应用场景和需求进行调整和完善。以上仅为基本的流程提供了一个参考。具体的代码实现应根据实际情况进行调整和修改。 ### 回答3: 在Unity3D使用最小乘法进行标定的具体代码如下所示: 1. 首先定义一个函数用于计算最小乘法的过程: ```c# public void LeastSquaresCalibration(Vector3[] worldPoints, Vector3[] imagePoints) { // 检查输入数据是否合法 if(worldPoints.Length != imagePoints.Length || worldPoints.Length < 4) { Debug.Log("输入数据不合法!"); return; } // 初始化变量和矩阵 Matrix4x4 projectionMatrix = new Matrix4x4(); Matrix4x4 lossMatrix = new Matrix4x4(); Matrix4x4.Mult(projectionMatrix.inverse, lossMatrix); // 根据最小乘法的公式计算标定参数 // ... // 输出标定结果 Debug.Log("标定结果:\n" + projectionMatrix); } ``` 2. 在需要调用标定函数的地方,传入世界坐标点和图像坐标点的数组: ```c# Vector3[] worldPoints = new Vector3[] { new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0) }; Vector3[] imagePoints = new Vector3[] { new Vector3(0, 0, 0), new Vector3(1, 0, 0), new Vector3(0, 1, 0), new Vector3(1, 1, 0) }; LeastSquaresCalibration(worldPoints, imagePoints); ``` 请注意,这只是一个简单的示例代码,实际应用中可能需要根据具体情况进行更加复杂的处理。最小乘法的具体实现可能需要引用数学库或自行编写计算相关矩阵和向量的函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值