C# 在Unity中使用带Arduino的操纵杆模块

C# 在Unity中使用带Arduino的操纵杆模块,c#,unity3d,arduino,hardware,joystick,C#,Unity3d,Arduino,Hardware,Joystick,我刚刚做了一个游戏,一个立方体在平台上移动,没有碰撞任何障碍物。我试图用一个带有Arduino UNO的操纵杆模块来控制运动。没有任何编译错误,运行良好。在完成一个关卡后,它开始滞后,平滑度就消失了(正如你所知,只有一个关卡,同一关卡一直在重新加载,现在我制作这个游戏只是为了学习)。此外,在关卡之后,Arduino通讯也会关闭,我确信它会关闭,因为每次关卡重新加载时,Arduino的灯都会重置。因此,总而言之,当Arduino连接时,它运行良好,并且只运行一次,没有任何问题。重新加载关卡后,它会

我刚刚做了一个游戏,一个立方体在平台上移动,没有碰撞任何障碍物。我试图用一个带有Arduino UNO的操纵杆模块来控制运动。没有任何编译错误,运行良好。在完成一个关卡后,它开始滞后,平滑度就消失了(正如你所知,只有一个关卡,同一关卡一直在重新加载,现在我制作这个游戏只是为了学习)。此外,在关卡之后,Arduino通讯也会关闭,我确信它会关闭,因为每次关卡重新加载时,Arduino的灯都会重置。因此,总而言之,当Arduino连接时,它运行良好,并且只运行一次,没有任何问题。重新加载关卡后,它会变得非常滞后,即使使用键盘输入也无法控制角色

这是游戏结束脚本

using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System.IO.Ports;

public class GameManager : MonoBehaviour
{
    public Text scoreEdit;
    public GameObject overText;
    bool gameHasEnded = false;
    public GameObject completeLevelUI;

    public PlayerMovement movementC;


    public void CompleteLevel()
    {
        completeLevelUI.SetActive(true);
    }

    public void EndGame()
    {
        if (gameHasEnded == false)
        {
            gameHasEnded = true;
            Debug.Log("Game Over");
            Over();
            Invoke("Restart", 4f);
            movementC.CloseCom();
        }
    }

    void Restart()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    }

    public void Over()
    {
        scoreEdit.color = Color.red;
        overText.SetActive(true);
    }
}
这是冲突脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO.Ports;


public class PlayerCollision : MonoBehaviour
{
    public PlayerMovement movement;


    void OnCollisionEnter(Collision collisionInfo)
    {
        if (collisionInfo.collider.tag == "Obstacle")
        {
            movement.enabled = false;
            FindObjectOfType<GameManager>().EndGame();
        }
    }
}
使用系统集合;
使用System.Collections.Generic;
使用UnityEngine;
使用System.IO.Ports;
公共类玩家集合:单一行为
{
公众游戏运动;
void onCollisionCenter(碰撞信息)
{
if(collisionInfo.collider.tag==“障碍物”)
{
movement.enabled=false;
FindObjectOfType().EndGame();
}
}
}
这是动作脚本

using System.Collections;
using UnityEngine;
using System.IO.Ports;

public class PlayerMovement : MonoBehaviour
{
    public Rigidbody rb;

    public float forwardForce = 4000f;
    public float sidewaysForce = 100f;
    public int CMD;

    public SerialPort sp = new SerialPort("COM7", 9600);

    // Start is called before the first frame update
    void Start()
    {
        sp.Open();
        sp.ReadTimeout = 1;
    }

    void FixedUpdate()
    {
        if (sp.IsOpen)
        {
            try
            {
                ReadCom();
                Move();
            }
            catch(System.Exception)
            {

            }
        }
        else
        {
            Move();
        }
    }

    // Update is called once per frame
    void Move()
    {
        rb.AddForce(0, 0, forwardForce * Time.deltaTime);

        if (Input.GetKey("d") || CMD == 6)
        {
            rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
        }

        if (Input.GetKey("a") || CMD == 4)
        {
            rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
        }

        if (Input.GetKey("w") || CMD == 8)
        {
            rb.AddForce(0, sidewaysForce * Time.deltaTime, 0, ForceMode.VelocityChange);
        }

        if (Input.GetKey("s") || CMD == 2)
        {
            rb.AddForce(0, -sidewaysForce * Time.deltaTime, 0, ForceMode.VelocityChange);
        }

        if (rb.position.y < -1f)
        {
            FindObjectOfType<GameManager>().EndGame();
        }
    }

    void ReadCom()
    {
        CMD = sp.ReadByte();
    }

    public void CloseCom()
    {
        sp.Close();
    }
}
public SerialPort sp = new SerialPort("COM7", 57600);
使用系统集合;
使用UnityEngine;
使用System.IO.Ports;
公共类玩家运动:单一行为
{
公共刚体;
公共浮力=4000f;
公共浮子侧向力=100f;
公共int CMD;
公共串行端口sp=新串行端口(“COM7”,9600);
//在第一帧更新之前调用Start
void Start()
{
sp.Open();
sp.ReadTimeout=1;
}
void FixedUpdate()
{
如果(sp.IsOpen)
{
尝试
{
ReadCom();
Move();
}
捕获(系统异常)
{
}
}
其他的
{
Move();
}
}
//每帧调用一次更新
无效移动()
{
rb.AddForce(0,0,forwardForce*Time.deltaTime);
if(Input.GetKey(“d”)| CMD==6)
{
rb.AddForce(侧向力*Time.deltaTime,0,0,ForceMode.VelocityChange);
}
if(Input.GetKey(“a”)| | CMD==4)
{
rb.AddForce(-sidewaysForce*Time.deltaTime,0,0,ForceMode.VelocityChange);
}
if(Input.GetKey(“w”)| | CMD==8)
{
rb.AddForce(0,侧向力*Time.deltaTime,0,力模式.VelocityChange);
}
if(Input.GetKey(“s”)| CMD==2)
{
rb.AddForce(0,-侧向力*Time.deltaTime,0,力模式.VelocityChange);
}
如果(径向位置y<-1f)
{
FindObjectOfType().EndGame();
}
}
void ReadCom()
{
CMD=sp.ReadByte();
}
公营机构
{
sp.Close();
}
}
这是Arduino代码

const int x = A0;
const int y = A1;
const int button = 7;

int curX = 0;
int curY = 0;
int curB = 1;

void setup() 
{
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(button, INPUT);
 
  Serial.begin(9600);
}

void loop() 
{
  curX = analogRead(x);
  curY = analogRead(y);
  curB = digitalRead(button);

 
  if(analogRead(x) >=1000)
  {
    Serial.write(6);
    Serial.flush();
    //Serial.println(6);
    delay(10);
  }else if(analogRead(x) <= 10)
  {
    Serial.write(4);
    Serial.flush();
    //Serial.println(4);
    delay(10);
  }else if (analogRead(y) <= 10)
  {
    Serial.write(8);
    Serial.flush();
    //Serialprintln(8);
    delay(10);
  }else if (analogRead(y) >= 1000)
  {
    Serial.write(2);
    Serial.flush();
    //Serialprintln(2);
    delay(10);
  }else 
  {
    Serial.write(0);
    Serial.flush();
    //Serial.println(0);
    delay(10);
  }
}
const int x=A0;
常数y=A1;
常数int按钮=7;
int-curX=0;
int curY=0;
整备整备=1;
无效设置()
{
引脚模式(A0,输入);
引脚模式(A1,输入);
pinMode(按钮,输入);
Serial.begin(9600);
}
void循环()
{
curX=模拟读数(x);
curY=模拟读数(y);
路缘=数字读取(按钮);
如果(读数(x)>=1000)
{
串行写入(6);
Serial.flush();
//序列号println(6);
延迟(10);

}如果我解决了这个问题,下面是答案

我将Arduino的波特率提高到57600(也可以是115200,但57600运行良好)

在Arduino脚本中更改代码的和平

Serial.begin(57600);
另外,我删除了所有的延迟函数,只在循环函数的末尾添加了一个延迟

和平的代码在运动脚本中改变

using System.Collections;
using UnityEngine;
using System.IO.Ports;

public class PlayerMovement : MonoBehaviour
{
    public Rigidbody rb;

    public float forwardForce = 4000f;
    public float sidewaysForce = 100f;
    public int CMD;

    public SerialPort sp = new SerialPort("COM7", 9600);

    // Start is called before the first frame update
    void Start()
    {
        sp.Open();
        sp.ReadTimeout = 1;
    }

    void FixedUpdate()
    {
        if (sp.IsOpen)
        {
            try
            {
                ReadCom();
                Move();
            }
            catch(System.Exception)
            {

            }
        }
        else
        {
            Move();
        }
    }

    // Update is called once per frame
    void Move()
    {
        rb.AddForce(0, 0, forwardForce * Time.deltaTime);

        if (Input.GetKey("d") || CMD == 6)
        {
            rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
        }

        if (Input.GetKey("a") || CMD == 4)
        {
            rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
        }

        if (Input.GetKey("w") || CMD == 8)
        {
            rb.AddForce(0, sidewaysForce * Time.deltaTime, 0, ForceMode.VelocityChange);
        }

        if (Input.GetKey("s") || CMD == 2)
        {
            rb.AddForce(0, -sidewaysForce * Time.deltaTime, 0, ForceMode.VelocityChange);
        }

        if (rb.position.y < -1f)
        {
            FindObjectOfType<GameManager>().EndGame();
        }
    }

    void ReadCom()
    {
        CMD = sp.ReadByte();
    }

    public void CloseCom()
    {
        sp.Close();
    }
}
public SerialPort sp = new SerialPort("COM7", 57600);

这解决了问题,但我不完全理解为什么它会被解决,因为正如我所说的,当Arduino插上电源时,它运行得很好,当水平仪重新加载时,它运行得不像第一次运行时那么平稳。唯一的解决办法是再次插上Arduino。但现在它工作得很好,所以问题就解决了。

我对操纵手柄了解不多,但是你说它似乎没有响应,我注意到你正在以蜗牛的速度(9600)运行串行通信,并且有延迟(10)在整个代码中都有。如果我想做一些有响应性的事情,我肯定会选择以更高的波特率运行串行,而不会告诉我的微控制器花时间旋转它的轮子。#Delta_G你是对的,它帮助了我。我将波特率更改为57600,删除了所有延迟功能,并为它添加了一个延迟循环结束功能。但我不明白为什么这解决了问题,因为正如我在插入Arduino时所说的,它运行时没有任何问题,但在重新加载关卡后,它的运行不如第一次运行时顺利。唯一的解决方案是再次插入Arduino。但它解决了问题,所以没问题,谢谢。我会去的115200或更多。为什么你认为你需要一个延迟呢?我想知道你是否在游戏结束时继续在游戏中发送串行数据,然后当游戏重新启动时,你有一堆缓冲数据要读取。当你重置端口时,你清除了所有这些,这样你就可以获得一个更好的游戏,然后在游戏结束时,它就会生成另一个完整的缓冲区。IDK,只是一个想法,但这应该是相对容易确定的。我尝试删除延迟,但后来游戏根本没有运行。也是的,有很多事情要做,以优化它,我会尝试所有的可能性,但现在它运行良好。也许我可以使用115200,看看它的性能如何。