顺利移动我的游戏对象的最佳方式?
Best way to move my Gameobject smoothly?
我在尝试平稳移动游戏对象时遇到问题。
我通过 TCP 协议每秒收到一个位置,我的游戏对象必须在该位置移动。所以我有我的开始位置,我的结束位置,我可以计算两个位置之间的距离 ,而且我知道我的游戏对象必须在 1 秒.
内以恒定速度移动到我的终点
我尝试了 3 种解决方案,它们是:Learp、MoveToward 和 SmoothDamp,但是 none 其中一个有效,我的游戏对象每次都只是从 A 点传送到 B 点。
这是我在代码中尝试的内容(字典中引用了我的游戏对象,我的游戏对象是平面):
// Distance between my 2 points
float step = Vector3.Distance(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y));
//Use of Lerp
//planeId_Object_Dictionnary[newPlane.Flight].transform.position = Vector3.Lerp(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y), step);
//Use of MoveTowards
planeId_Object_Dictionnary[newPlane.Flight].transform.position = Vector3.MoveTowards(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y), step);
//Use of SmoothDamp
//planeId_Object_Dictionnary[newPlane.Flight].transform.position = Vector3.SmoothDamp(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y), ref newPlane.GroundSpeed, 1);
该代码是在我的更新中以这种方式调用的函数:
void Update () {
lock (threadLock)
{
// Message receive from my TCP Protocol
while (q_orders.Count > 0)
{
switch (q_orders.Dequeue())
{
case OrderType.trackmovedevent:
aircraftMajInfos(q_args.Dequeue()); // My function to move my Object
break;
}
}
}
}
我必须说你对这三个功能的理解完全错误。它们应该在多次更新中被调用,而不是一次。
在这种情况下我推荐MoveTowards
。因为SmoothDamp
并不是匀速移动物体,要使用Lerp
,需要计算两点之间的比例(注意,如果加上量,就可以不断移动物体到每个固定更新的 t 参数)。
这是我为游戏对象的 MonoBehaviour 编写的代码片段
const float moveTime = 1;
Vector3 target, step;
void Update () {
transform.position = Vector3.MoveTowards(transform.position, target,
step / moveTime * Time.deltaTime);
}
// Call this method to set the new target (the currently received position from network)
public void SetTarget (Vector3 positon) {
target = positon;
step = Vector3.Distance(transform.position, target);
}
Time.deltaTime
是更新之间的间隔(调用Update ()
函数的地方)
最好使用补间引擎,例如http://dotween.demigiant.com/。
如果你安装了 Dotween 那么你可以简单地使用
transform.DOMove(new vector3(1 ,0 , 1) , duration);
您还可以为补间设置缓动。或使用 Oncomplete 函数;
transform.DOMove(new vector3(1 ,0 , 1) , duration)
.SetEase(Ease.OutCubic)
.OnCompelete(() => { shouldClose = true; });
我建议如下:
- 创建一个新脚本"ObjectMover"(可能不是最好的名字)并将其应用到您希望能够移动的游戏对象上。
- 在脚本中创建一个 public 方法:MoveToNewPos(Vector3 newPos),它存储您使用此对象瞄准的新位置。
在 "ObjectMover" 的 Update 方法中使用 lerp 或使用 step / moveTime * Time.deltaTime 自己计算步进以移动到想要的新位置并且仅将速度调整为您想要的外观和感觉.
从您的 "main" 脚本执行 theObjectIWantToMove.GetComponent().MoveToNewPos(newPos);它将顺利移动到那里。
我在尝试平稳移动游戏对象时遇到问题。
我通过 TCP 协议每秒收到一个位置,我的游戏对象必须在该位置移动。所以我有我的开始位置,我的结束位置,我可以计算两个位置之间的距离 ,而且我知道我的游戏对象必须在 1 秒.
内以恒定速度移动到我的终点我尝试了 3 种解决方案,它们是:Learp、MoveToward 和 SmoothDamp,但是 none 其中一个有效,我的游戏对象每次都只是从 A 点传送到 B 点。
这是我在代码中尝试的内容(字典中引用了我的游戏对象,我的游戏对象是平面):
// Distance between my 2 points
float step = Vector3.Distance(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y));
//Use of Lerp
//planeId_Object_Dictionnary[newPlane.Flight].transform.position = Vector3.Lerp(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y), step);
//Use of MoveTowards
planeId_Object_Dictionnary[newPlane.Flight].transform.position = Vector3.MoveTowards(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y), step);
//Use of SmoothDamp
//planeId_Object_Dictionnary[newPlane.Flight].transform.position = Vector3.SmoothDamp(planeId_Object_Dictionnary[newPlane.Flight].transform.position, new Vector3((float)newPlane.X, (float)newPlane.Afl / (3.2808f * 1852f), (float)newPlane.Y), ref newPlane.GroundSpeed, 1);
该代码是在我的更新中以这种方式调用的函数:
void Update () {
lock (threadLock)
{
// Message receive from my TCP Protocol
while (q_orders.Count > 0)
{
switch (q_orders.Dequeue())
{
case OrderType.trackmovedevent:
aircraftMajInfos(q_args.Dequeue()); // My function to move my Object
break;
}
}
}
}
我必须说你对这三个功能的理解完全错误。它们应该在多次更新中被调用,而不是一次。
在这种情况下我推荐MoveTowards
。因为SmoothDamp
并不是匀速移动物体,要使用Lerp
,需要计算两点之间的比例(注意,如果加上量,就可以不断移动物体到每个固定更新的 t 参数)。
这是我为游戏对象的 MonoBehaviour 编写的代码片段
const float moveTime = 1;
Vector3 target, step;
void Update () {
transform.position = Vector3.MoveTowards(transform.position, target,
step / moveTime * Time.deltaTime);
}
// Call this method to set the new target (the currently received position from network)
public void SetTarget (Vector3 positon) {
target = positon;
step = Vector3.Distance(transform.position, target);
}
Time.deltaTime
是更新之间的间隔(调用Update ()
函数的地方)
最好使用补间引擎,例如http://dotween.demigiant.com/。
如果你安装了 Dotween 那么你可以简单地使用
transform.DOMove(new vector3(1 ,0 , 1) , duration);
您还可以为补间设置缓动。或使用 Oncomplete 函数;
transform.DOMove(new vector3(1 ,0 , 1) , duration)
.SetEase(Ease.OutCubic)
.OnCompelete(() => { shouldClose = true; });
我建议如下:
- 创建一个新脚本"ObjectMover"(可能不是最好的名字)并将其应用到您希望能够移动的游戏对象上。
- 在脚本中创建一个 public 方法:MoveToNewPos(Vector3 newPos),它存储您使用此对象瞄准的新位置。
在 "ObjectMover" 的 Update 方法中使用 lerp 或使用 step / moveTime * Time.deltaTime 自己计算步进以移动到想要的新位置并且仅将速度调整为您想要的外观和感觉.
从您的 "main" 脚本执行 theObjectIWantToMove.GetComponent().MoveToNewPos(newPos);它将顺利移动到那里。