- Home /
Simultaneously moving GameObjects using C# script.
Hi,
Im working on a game where you need to move a cube past multiple obstacles (also cubes). Im trying to add some obstacles that move from one side of the track to the other, and soon as they reach one of the sides, they start to move to the other again. For efficiency i want to controll all of them with just 1 C# script.
My code works perfectly, as long as there is just 1 moving obstacle. Soon as I add more they will move to one of the sides and stay there. The moving obstacles have as tag "MovingWall"
Here is my code, any suggestions on how to make this work?
using UnityEngine;
public class MovingWalls : MonoBehaviour {
bool moveToRight = true;
GameObject[] walls;
void Start()
{
walls = GameObject.FindGameObjectsWithTag("MovingWall"); //create list of all the moving walls
}
void FixedUpdate () {
foreach (GameObject wall in walls)
{
float wallx = wall.transform.position.x;
if (wall.transform.position.x >= 12.5) //12.5
{
moveToRight = false;
}
else if (wall.transform.position.x <= -12.5)
{
moveToRight = true;
}
if (moveToRight)
{
wallx += 10f * Time.deltaTime;
}
else
{
wallx += -10f * Time.deltaTime;
}
wall.transform.position = new Vector3(wallx, wall.transform.position.y, wall.transform.position.z);
}
}
}
Sidenote: this is my first post on this forum, if i did anything wrong dont hesitate to tell me.
Answer by tsnyder321 · Jul 18, 2017 at 07:05 PM
Here is a quick script I wrote that takes into account my suggestion. You can place it on your cubes to control their speeds and when they change directions (xMax and xMin).
using UnityEngine;
public class MovingWall : MonoBehaviour
{
//Properties visible in the unity editor
[SerializeField] float xMax = 12.5f;
[SerializeField] float xMin= -12.5f;
[SerializeField] float speed = 10.0f;
bool movingRight = true;
Vector3 newPosition = Vector3.zero;
// Update is called once per frame
void Update ()
{
//switch directions as needed based on the xMin and xMax
if(transform.position.x > xMax)
{
movingRight = false;
}
else if(transform.position.x < xMin)
{
movingRight = true;
}
//reset the newPosition var to the attached object's current position
newPosition = transform.position;
//alter the position
newPosition.x += (movingRight) ? speed * Time.deltaTime : -speed * Time.deltaTime;
//set the new position
transform.position = newPosition;
}
}
Works like a charm, thank you.
This is my first Unity game ever, hence i didnt know it was possbile to call transform directly on the GameObject you add the script to. Would have saved me a lot of trouble....
Well congrats on taking your first steps in making a game in Unity! It is a truly remarkable game engine and the community is amazing.
Good luck on your game!
Can definitely confirm the last thing you said
Answer by tsnyder321 · Jul 18, 2017 at 03:34 PM
I believe your script will work fine, as long as your only have a single instance of it in your scene. I tested this to make sure, and it does. If you have 2 or more instances of this script in your scene, the cubes will speed up and stop at the one side.
Create yourself an empty game object in your scene (maybe "Cube Controller") and only place the script on it. It will then find all the tagged cubes and move them like you want.
Suggestion: I would suggest re-writing your script so it CAN be placed on your individual cube objects, exposing a variable "speed" to the editor. That way you will have more control over the individual cubes, which can give your game some variety. Just a thought. :)
Thank you! @tsnyder321
The cubes ar moving now, but soon as one of them hits a side they all change direction. I only want the cube that hit the side to change direction. I think I'm capable of solving this problem myself, but in case Im not: have you also got any idea how to fix this problem?
Thanks in advance
Really your best best is to follow tsnyder's suggestion. Rework the script so it controls only the game object to which it is attached. Otherwise, you'll have to keep track of a "move right" variable for each item being tracked by your script. You're going to keep putting duct tape on a situation where there is a clear and easy solution
I was right in the middle of writing a post saying that Br4m3000 would have to keep track of a list of boolean flags since he has the cube objects tripping a single boolean flag when they reach the 12.5 and -12.5 x position. Thanks for your response on this Habitablaba.
Answer by ShadyProductions · Jul 18, 2017 at 06:52 PM
Here is your ductaped solution like Habitablaba says lol.
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class MovingWalls : MonoBehaviour
{
private IEnumerable<WallObject> walls;
void Start()
{
walls = GameObject.FindGameObjectsWithTag("MovingWall").Select(f => new WallObject { Wall = f, MoveToRight = false});
}
private class WallObject
{
public GameObject Wall;
public bool MoveToRight;
}
void FixedUpdate()
{
foreach (WallObject obj in walls)
{
float wallx = obj.Wall.transform.position.x;
if (obj.Wall.transform.position.x >= 12.5) //12.5
{
obj.MoveToRight = false;
}
else if (obj.Wall.transform.position.x <= -12.5)
{
obj.MoveToRight = true;
}
if (obj.MoveToRight)
{
wallx += 10f * Time.deltaTime;
}
else
{
wallx += -10f * Time.deltaTime;
}
obj.Wall.transform.position = new Vector3(wallx, obj.Wall.transform.position.y, obj.Wall.transform.position.z);
}
}
}
This hurts to look at, lol. Its like... taking a working, well engineered car and replacing the doors with duct tape
Hey atleast the car would still work aha :P