- Home /
How do I move one of many instantiated gameobjects ONLY if it's currently selected in a list?
I'm new at using Unity with C# and help is really appreciated. I have two scripts. One that instantiates a gameobject prefab when I press spacebar key and adds it to a list. I can also cycle through the list with left/right arrow keys. (seems to work fine)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeSelector : MonoBehaviour
{
Vector2 CubeSpawnPosition;
public GameObject CubeObject;
public GameObject SelectedCubeObject;
public int CurrentCubeInList;
public List<GameObject> CubeList = new List<GameObject>();
// Start is called before the first frame update
void Start()
{
CubeSpawnPosition = new Vector2(5, 10);
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown("right"))
{
CurrentCubeInList += 1;
}
if (Input.GetKeyDown("left"))
{
CurrentCubeInList -= 1;
}
if (CurrentCubeInList >= CubeList.Count)
{
CurrentCubeInList = 0;
}
if (CurrentCubeInList < 0)
{
CurrentCubeInList = CubeList.Count - 1;
}
SelectedCubeObject = CubeList[CurrentCubeInList];
if (Input.GetKeyDown("space"))
{
Instantiate(CubeObject, CubeSpawnPosition, Quaternion.identity);
foreach (GameObject thisCube in GameObject.FindGameObjectsWithTag("Cube"))
{
CubeList.Add(thisCube);
}
}
}
}
and I have another script that controls the gameobjects movement which is attached as a component to the gameobject prefab and so also all clones of that prefab individually.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CubeController : MonoBehaviour
{
private Vector3 CubeTarget;
private float CubeSpeed = 3f;
CubeSelector CubeSelectorScript;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
if (gameObject == CubeSelectorScript.SelectedCubeObject)
{
CubeTarget = Camera.main.ScreenToWorldPoint(Input.mousePosition);
CubeTarget.z = transform.position.z;
CubeTarget.y = transform.position.y;
transform.position = Vector3.MoveTowards(transform.position, CubeTarget, CubeSpeed * Time.deltaTime);
Debug.Log("Cube at " + CubeSelectorScript.CurrentCubeInList + " Moved.");
}
}
}
}
What I'm trying to figure out is how to make it so that ONLY gameobjects that are currently selected in the other script's list (from cycling through the list) will do the movement. any help is appreciated :)
Answer by MurphyMurph_21 · Nov 21, 2020 at 12:33 PM
@hzata . Ok so this is the revised version of what you asked for. I think I got everything. Let me know if it doesn't work, I will do my best to fix it. Try and read the code and see if you understand it so you can learn as well.
using UnityEngine;
public class CubeController : MonoBehaviour
{
CubeSelector cubeSelector; // creates a reference to cube spawner(CubeSelector)
public Vector3 originalMousePosition;
public Vector3 cubeTargetPosition;
private float speed;
[SerializeField] private bool cubeKeepMoving = false;
public Color originalColor;
private void Awake()
{
originalColor = GetComponent<MeshRenderer>().material.color; // stores original color
cubeSelector = FindObjectOfType<CubeSelector>(); // finds the 1st Cube Selector (should only be 1 per scene)
speed = cubeSelector.cubeSpeed; // gets the speed from the cube spawner
}
void Update()
{
speed = cubeSelector.cubeSpeed;
if (Input.GetMouseButtonDown(0))
{
if (!cubeKeepMoving)
{
// got some code from here, great resource
// please keep the link to credit the author
// https://gamedevbeginner.com/how-to-convert-the-mouse-position-to-world-space-in-unity-2d-3d/
originalMousePosition = Input.mousePosition; // gets mouse position
originalMousePosition.z = CubeSelector.maxDistance; // adjusts the Z-axis
cubeTargetPosition = Camera.main.ScreenToWorldPoint(originalMousePosition);
// moves from one position to another and stops at the final position
transform.position = Vector3.MoveTowards(transform.position, cubeTargetPosition, speed * Time.deltaTime); // Thanks for showing me this, i didnt know about this method
Debug.Log("Cube at " + gameObject.name + " Moved."); // can be deleted
cubeKeepMoving = true;
}
}
if (cubeKeepMoving)
{
transform.position = Vector3.MoveTowards(transform.position, cubeTargetPosition, speed * Time.deltaTime);
}
}
}
For this to work as is only have 1 CubeSelector per scene
using System.Collections.Generic;
using UnityEngine;
// No license no need to credit me personally
// Please keep the links where I borrowed code from to credit the original author's
public class CubeSelector : MonoBehaviour
{
[Header("Cube Prefab References")]
public GameObject cubePrefab;
public static List<GameObject> CubeList = new List<GameObject>();
[Header("Cube Properties")]
public static float maxDistance = 50f; // how far from camera will the mouse click register // Z-axis
public float cubeSpeed = 2f; // how fast cube moves
[SerializeField] private Color selectedCubeColor;
[SerializeField] private int CurrentCubeInList = 0;
[SerializeField] private Vector3 CubeSpawnPosition; // default is Vector3(0f, 0f, 0f)
[SerializeField] private static int nameCounter = 1; // keeps track of how many cubes have been created
void Update()
{
if (Input.GetKeyDown("right")) // cycles thru cubes
{
if (CurrentCubeInList >= CubeList.Count - 1)
{
CurrentCubeInList = 0;
}
else
{
CurrentCubeInList += 1;
}
}
if (Input.GetKeyDown("left")) // cycles thru cubes
{
if (CurrentCubeInList <= 0)
{
if(CubeList.Count == 0)
{
CurrentCubeInList = 0;
}
else
{
CurrentCubeInList = CubeList.Count - 1;
}
}
else
{
CurrentCubeInList -= 1;
}
}
if (CubeList.Count >= 0)
{
foreach (GameObject cube in CubeList)
{
CubeController cubeController = cube.GetComponent<CubeController>(); // Gets CubeController from cube
if (CubeList.IndexOf(cube) != CurrentCubeInList)
{
cube.GetComponent<Renderer>().material.color = cubeController.originalColor; // changes all cubes back to starting color
}
else
{
cube.GetComponent<Renderer>().material.color = selectedCubeColor; // changes the color of selected cube
}
if (cube == CubeList[CurrentCubeInList] && Input.GetMouseButtonDown(0))
{
// gets mouse position and adjusts the Z-axis
cubeController.originalMousePosition = Input.mousePosition;
cubeController.originalMousePosition.z = maxDistance;
cubeController.cubeTargetPosition = Camera.main.ScreenToWorldPoint(cubeController.originalMousePosition);
// moves the cube to new destination // Time.deltaTime makes it smooth(framerate independent so its not jittery)
cube.transform.position = Vector3.MoveTowards(cube.transform.position, cubeController.cubeTargetPosition, cubeSpeed * Time.deltaTime);
Debug.Log($"{cube.name} is now moving to new position at : {cubeController.cubeTargetPosition}");
}
}
}
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject thisCube; // Temp variable to access the instantiated prefab
thisCube = Instantiate(cubePrefab, CubeSpawnPosition, Quaternion.identity);
thisCube.name = $"Cube {nameCounter}";
nameCounter++; // adds 1 to the name counter
thisCube.GetComponent<CubeController>().enabled = true; // makes sure new cube can move
CubeList.Add(thisCube); // adds new cube to list
if(CubeList.Count > 1)
{
CurrentCubeInList = CubeList.Count -1; // updates the CurrentCube number // actual list starts at index 0 not at index 1
}
Debug.Log($"Added {thisCube.name} to the CubeList :: Current count is {CubeList.Count}");
}
}
}
Thanks @$$anonymous$$urphy$$anonymous$$urph_21 a huge help!
the code worked just fine for what I asked but I might have missed a small detail. I'm trying to figure out how to make an individual cube ignore further if (Input.Get$$anonymous$$ouseButtonDown(0)){} if it is not currently selected. I want the cube to continue moving to the position it was originally, just that while not selected, ignore the part where it sets a new target position for that cube when I mouse click. I tried splitting the movement and targetting code into separate scripts and to disable just the targetting script, but it came up with errors. any help is appreciated!
@hzata Your welcome! Well it looks like that was big detail lol. So if I understand correctly, if the current cube that is selected becomes unselected you want that cube to return to its original position. And you want the newly selected cube to move to a new location depending on where you click the mouse? and also do you want incremental movement(moves a little every time you click the mouse) or 1 smooth transition movement(you press the mouse click button once and it moves to the destination at a certain speed)
@$$anonymous$$urphy$$anonymous$$urph_21 thanks for the reply! I will try to explain better :)
I want all cubes to move in a smooth transition over time to their target position.
$$anonymous$$ouse clicks should set the target position for the selected cube. I want cubes to continue moving to their target position at all times regardless of being selected or not.
If a cube is not selected I want it to ignore mouseclicks. (meaning its target position doesn't change when the mouse clicks somewhere)
If a cube is selected i want it to respond to mouseclicks (meaning its target position will be set whenever the mouse clicks somewhere)
thanks @$$anonymous$$urphy$$anonymous$$urph_21 !! I figured it out and it works perfectly now. thanks again for your patience and all the help
@hzata Your welcome man. I actually had fun trying to figure this out so thank you for a good challenge!
Your answer
Follow this Question
Related Questions
Distribute terrain in zones 3 Answers
Keep list of GameObjects between scenes 2 Answers
How do I move a gameobject ONLY if it's currently selected in my list of gameobjects? 2 Answers
Multiple Cars not working 1 Answer
using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers