【问题标题】:Moving objects back and forth [duplicate]来回移动物体[重复]
【发布时间】:2017-09-05 05:07:26
【问题描述】:

我正在尝试移动多个对象,同时从 A 点移动到 B 点并再次返回,循环以作为阻挡玩家的障碍。

我试过了

StartCoroutine(Oscillate(OscillationFunction.Sine, 1f));
  public IEnumerator Oscillate(OscillationFunction method, float scalar)
  right = GameObject.FindGameObjectsWithTag("MovingObs2");
                foreach (GameObject r in right)
                {
                    startPos = r.transform.position;    
                    v = startPos;
                    v.x = (r.transform.position.x + (Mathf.Cos(Time.time) * scalar));
                    r.transform.position = v;
                    yield return new WaitForSeconds(2);
                    r.transform.position = startPos;
                }

还有其他,但它们都很难控制在距起始位置理想的距离和速度内。太快了,也太远了。

我尝试了一条看似简单的线,对我来说更容易理解。

 v.x = l.transform.position.x + speed * Time.deltaTime;
            l.transform.position = v;

但由于我在 foreach 循环中使用数组,我不知道如何保存每个 GameObjects 的 transform.position,以便它可以用作每次反转对象运动方向的条件它到达 A 点或 B 点的时间。

   if (l.transform.position.x <= startPos.x || l.transform.position.x >= startPos.x + endPos.x)
        {
            speed *= -1;
        }

编辑:如果我问了一个重复的问题,我深表歉意,我认为由于数组中涉及的对象数量而有所不同。

【问题讨论】:

  • 为什么不让每个对象通过附加到对象的脚本来处理自己的移动,而不是让控制器对象尝试移动所有对象?
  • 任何动作都应该是Time.deltaTime的函数,正如你所怀疑的那样
  • @ScottChamberlain 我实际上认为如果将其编写在一起会更容易和更有条理,但显然我错了。我太忙于让它工作了,谢谢你的评论,很有启发性

标签: c# unity3d unity5


【解决方案1】:

我试图假设可以解决您的所有问题,请参阅下面的代码。

Time.deltaTime 不是必需的,因为您的代码(和我的)使用 Time.time 来计算每次对象的位置。

我还建议(如果可能的话)不要把所有的东西都放在脚本上,而是给每个对象一个摇摆脚本,并且尽量不使用 CoRoutine。但是为了回答你的问题,我会告诉你如何去做。

我创建了一个内部类,将目标游戏对象及其 startPosition 存储在“Init”列表中。稍后您可以简单地遍历此列表并始终拥有起始位置。

您需要在“Osciallate”例程中进行无限循环,并且需要等待每一轮。在您的示例中,您将 Wait 放在错误的位置,因此它在移动每个对象后等待,并在第一次运行所有这些对象后停止。

代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OscilateObs : MonoBehaviour {

    // internal class where all gameobjects and their startposition will be saved
    internal class OscGameObjects
    {
        public GameObject gameObject;
        public Vector3 startPosition;
    }

    // Here the information of all gameObjects stored in a list
    private List<OscGameObjects> objectList;

    public float updateSpeed = 0.05f;
    public float oscScalar = 2f;

    public enum OscillationFunction {
        Sine = 1
    }

    void Start () {
        // First, the gameobjects have to saved to our internal List
        InitializeOscGameObjects();

        // Start the Corotine
        StartCoroutine(Oscillate(OscillationFunction.Sine, oscScalar));
    }

    private void InitializeOscGameObjects()
    {
        var objects = GameObject.FindGameObjectsWithTag("MovingObs2");

        objectList = new List<OscGameObjects>();
        foreach (var o in objects)
        {
            var oscObject = new OscGameObjects();
            oscObject.gameObject = o;
            oscObject.startPosition = o.transform.position;

            objectList.Add(oscObject);
        }
    }

    public IEnumerator Oscillate(OscillationFunction method, float scalar)
    {
        // Loop forever
        while(true)
        {
            foreach (var element in objectList)
            {
                var currentPosition = element.gameObject.transform.position;
                currentPosition.x = element.startPosition.x + Mathf.Cos(Time.time) * scalar;
                element.gameObject.transform.position = currentPosition;

            }
            yield return new WaitForSeconds(updateSpeed);
        }

    }

}

编辑:

我忘记了意思:

1) 我建议对运动使用“动画”组件,而根本不使用 C#,因此您可以根据需要更改行为并且更加灵活。

2) 如果可能的话,我还建议制作父“GameObject”并仅移动它并将“MovingOb2”简单地作为子对象。

EDIT2:

为每个对象添加延迟增量,因此它们不会运行同步:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OscilateObs : MonoBehaviour {

    // internal class where all gameobjects and their startposition will be saved
    internal class OscGameObjects
    {
        public GameObject gameObject;
        public Vector3 startPosition;
        public float waitCount;
    }

    // Here the information of all gameObjects stored in a list
    private List<OscGameObjects> objectList;

    public float updateSpeed = 0.05f;
    public float oscScalar = 2f;
    public float waitIncrementTime = 0.01f;

    public enum OscillationFunction {
        Sine = 1
    }

    void Start () {
        // First, the gameobjects have to saved to our internal List
        InitializeOscGameObjects();

        // Start the Corotine
        StartCoroutine(Oscillate(OscillationFunction.Sine, oscScalar));
    }

    private void InitializeOscGameObjects()
    {
        var objects = GameObject.FindGameObjectsWithTag("MovingObs2");

        objectList = new List<OscGameObjects>();

        float i = 0;
        foreach (var o in objects)
        {
            i += waitIncrementTime;
            var oscObject = new OscGameObjects();
            oscObject.gameObject = o;
            oscObject.startPosition = o.transform.position;
            oscObject.waitCount = i;
            objectList.Add(oscObject);
        }
    }

    public IEnumerator Oscillate(OscillationFunction method, float scalar)
    {
        // Loop forever
        while(true)
        {
            foreach (var element in objectList)
            {
                var currentPosition = element.gameObject.transform.position;
                currentPosition.x = element.startPosition.x + Mathf.Cos(Time.time + element.waitCount) * scalar;
                element.gameObject.transform.position = currentPosition;

            }
            yield return new WaitForSeconds(updateSpeed);
        }

    }

}

【讨论】:

  • 谢谢,我正在研究它,非常感谢,我自己无法修复它。我没有意识到我把等待功能放在了错误的地方。我想知道为什么它也会不规律地移动。
  • 嗨,Seiren,谢谢你,很高兴听到它有效。如果这符合您的问题,请不要忘记将此标记为正确答案。如果您需要其他内容,请告诉我。
  • 非常感谢,克里斯蒂安!你帮了大忙。如果没有问题,我想问一下,在执行列表的transform.position时,我如何以增量延迟开始?例如,对象 1 将在块 1 之后移动 0.1 秒,对象 3 将在块 2 之后开始移动,依此类推。
  • 我现在添加了延迟增量,希望这是您想要的。它们在同一时间开始,但从不同的位置开始,这使它们异步移动。我希望这是你想要的
  • 非常感谢!我在发现编程中的逻辑工作方面还有很长的路要走,你教会了我很多东西,我真的很感激!!
【解决方案2】:

它们都很难控制在距起始位置理想的距离和速度内。太快了,也太远了

在开始修改代码结构之前,我建议您坚持使用余弦函数,但要让自己了解(非常简单)可以操纵输出频率和幅度的方式。这些知识将很好地为您服务(如果这个问题是您的普通项目的典型问题)并且可以轻松解决问题。

如果太快,您可以通过将输入(始终是绝对时间)乘以 0.0 到 +1.0(不包括)之间的常数系数来降低频率(或增加波长/周期)。

如果太远,可以通过将输出乘以 0.0 到 +1.0(不包括)之间的常数系数来减小幅度。

您只需要选择两个常量并通过运行程序并查看您的喜好来调整口味。

【讨论】:

  • 非常感谢您的解释,它让我对它的工作原理有了更多的了解。我仍在尝试掌握数学函数的工作原理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多