Unity3D: How can I move GameObjects from the same script independently?

3

I created a script in Unity3D that causes a GameObject to move sinusoidal.

The movement occurs perfectly, but when more than one GameObject containing this script is in the scene all move like a mirror of each other and not in a relative way, leaving the game very artificial.

I tried to use local placement and even then I could not solve the problem.

Here is the code:

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

public class Enemy4 : Nave {

 public float horizontalSpeed;
 public int yFactor;
 private float count = 3;
 private Vector3 s;
 private bool setPos = false;
 private float x;
 private float y;
 // Use this for initialization
 void Start () {
     x = 0;
     y = 0;
     s = transform.position;
     side = Side.defside.ENEMY;
 }

 // Update is called once per frame
 void Update () {
     y += yFactor * Time.deltaTime;
     x = Mathf.Sin (Time.time) * horizontalSpeed;
     transform.position = s + new Vector3 (x,y, 0);
 }

}
    
asked by anonymous 17.02.2017 / 20:53

1 answer

2

Sine waves

A sine wave has three relevant properties:

  • Frequency - This is the inverse of the distance between two peaks of a sine wave.

  • Amplitude - It is the difference between the peak height of the wave valley.

  • Phase - It is the part of the sine wave in which an object that moves by it is.

For example, let's assume that x and y are two consecutive wave peaks, so that:

- [a] x < y ,
- [b] Mathf.Sin(x) = Mathf.Sin(y) = p ,
- [c] does not exist t such that ( x < t < y and Mathf.Sin(t) = 1 ) and
- [d] for all b real -a <= Mathf.Sin(b) <= a .

Thus, the frequency would be given by 1 / (y - x) . The amplitude is 2 * a . The phase is given by t to the expression f(t) , where f is its senoid function (not necessarily the sin function itself, since f(x) = 2 * Mathf.Sin(x) is also a senoid function).

Analyzing your code

You are using the following to define the position of your object:

x = Mathf.Sin (Time.time) * horizontalSpeed;

Its sinusoidal function in this case is f(x) = Mathf.Sin (Time.time) * horizontalSpeed . The horizontalSpeed ends up being the amplitude. The phase is given by Time.time and the frequency is 2π seconds . This means that your objects will have a position that always oscillates in 2π seconds cycles and all will be synchronized as the wave phase.

The solution is to introduce something that causes them to become out of sync with the phase and how often.

In addition, use FixedUpdate instead of Update . %% Of% has consistent time intervals and is useful for updating game logic, while FixedUpdate is mostly intended to prepare rendering on the screen.

Resulting code

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

public class Enemy4 : Nave {

    public float horizontalSpeed;
    public int yFactor;
    public float frequency;
    public float phaseOffset;
    private float count = 3;
    private Vector3 s;
    private bool setPos = false;
    private float x;
    private float y;

    void Start() {
        x = 0;
        y = 0;
        s = transform.position;
        side = Side.defside.ENEMY;
    }

    void FixedUpdate() {
        y += yFactor * Time.deltaTime;
        x = Mathf.Sin(Time.time * frequency / Mathf.PI + phaseOffset) * horizontalSpeed;
        transform.position = s + new Vector3(x, y, 0);
    }
}

The value of Update will be the number of times per second that you want your object to cycle through a full cycle in the wave (and can not be zero). The value of frequency defines the phase in which the object is when the time is zero. These values, you can set a different for each object or put some random number whatever, according to what you think best.

    
18.02.2017 / 06:41