来回移动物体

Moving objects back and forth

我正在尝试移动多个对象,同时从 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 循环中使用数组,我不知道如何保留每个游戏对象的 transform.position,以便它可以用作反转方向的条件物体每次到达 A 点或 B 点时的移动。

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

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

我试着假设解决了你所有的问题,请看下面的代码。

不需要

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

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

我创建了一个内部 class,用于将目标游戏对象及其 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) 我建议使用 "Animation" 组件进行移动而不使用 C#,这样您可以根据需要更改行为并且更加灵活。

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

编辑2:

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

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);
        }

    }

}

they're all difficult to contain within a desirable distance and speed from the starting position. It's too fast, and too far

在您开始修改代码结构之前,我建议您坚持使用余弦函数,但要了解(非常简单的)操作输出频率和振幅的方式。这些知识将为您提供很好的帮助(如果这个问题是您的一般项目的典型问题)并且可以轻松解决问题。

如果速度太快,您可以通过将输入(始终是绝对时间)乘以 0.0 到 +1.0(不含)之间的常数系数来降低频率(或增加 wavelength/period)。

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

您只需要选择两个常量,然后根据 运行 程序进行调整,然后看看您是否喜欢它。