- Home /
Change rigidbody values on mutliple objects (ARRAY)
Hello! I'm working on a game where I need to change the values of multiple objects with the same tag.
The idea is that the rigidbody only moves while the player does.
I have code that works, but only for one object because, despite scouring the forums and documentation for hours, I don't understand arrays.
Essentially the code:
Finds the character controller
Detects if it's moving
If so, finds the object tagged "rbTime" and lets it move.
Else, finds the object tagged "rbTime" and stops it.
The issue is that I need this to work on ALL objects tagged "rbTime", not just one.
Here's my code - can someone help me make it work with all objects tagged and explain why it works?
#pragma strict
public var player : GameObject;
var isStopped : boolean = false;
function Start() {
}
function Update () {
var controller : CharacterController = player.GetComponent(CharacterController);
if(controller.velocity.magnitude < 1) {
physStop();
} else {
physStart();
}
}
function physStop() {
var b : GameObject = GameObject.FindGameObjectWithTag ("rbTime");
var rb = b.GetComponent(Rigidbody);
if (isStopped == false) {
rb.velocity = Vector3.zero;
rb.useGravity = false;
rb.isKinematic = true;
isStopped = true;
}
}
function physStart() {
var b : GameObject = GameObject.FindGameObjectWithTag ("rbTime");
var rb = b.GetComponent(Rigidbody);
if (isStopped == true) {
rb.isKinematic = false;
rb.useGravity = true;
isStopped = false;
}
}
Thanks!
-Sam
Answer by koray1396 · Apr 06, 2014 at 10:31 PM
Use FindGameObjectsWithTag instead of "Object"
put them in a list or array
apply the method for each item in the array using a loop
Hello!
Thank you for the reply. I do know that I need to use an array, but using a loop is new to me. Can you please show how I would use a loop to apply the method for all objects? If possible, modifying the original script?
ok, you can use lists. add the following line on top of your script, in order to be able to use lists.
import System.Collections.Generic;
then define a variable for this list above start();
var rbTimeObjects : List.<GameObject>;
You would want to store all rbTime objects once on Start, it would be waste of resources if you search for the same all the time. Therefore inside function Start();
rbTimeObjects = = new List.<GameObject>(FindGameObjectsWithTag("rbTime"));
However, if these objects will not stay the same, you can check them on every update, putting it right under update.
Now objects with rbTime tag are stored in rbTimeObjects, you can do whatever you need with them.
foreach(var b: GameObject in rbTimeObjects){
var rb = b.GetComponent(Rigidbody);
if (isStopped == false) {
rb.velocity = Vector3.zero;
rb.useGravity = false;
rb.is$$anonymous$$inematic = true;
isStopped = true;
}
}
I'm not a javascript user, and i can not test this at the moment, but this is the general idea. I believe below also would be useful for you.
http://wiki.unity3d.com/index.php?title=Which_$$anonymous$$ind_Of_Array_Or_Collection_Should_I_Use?
https://unity3d.com/learn/tutorials/modules/beginner/scripting/loops
It works great - I had to translate some parts into Javascript, but I get this error:
Cannot convert 'UnityEngine.GameObject[]' to 'System.Collections.Generic.List.'.
When creating the List variable:
var rbTimeObjects : List.< GameObject > = new List.< GameObject >();
(I assume the same error could be produced in C#) Aside from that, the code is error-free!
Thanks for your help so far!
-Sam
The error is a conflict of array and list, and probably caused by the following line, sorry about that.
you should note that, FindGameObjectsWithTag returns an array, which is different from a list. Lists are easier to handle.
rbTimeObjects = = new List.<GameObject>(FindGameObjectsWithTag("rbTime"));
Ins$$anonymous$$d, you can create a foreach loop for the items tagged with "rbTime".
foreach (var item: GameObject in FindGameObjectsWithTag("rbTime")){
rbTimeObjects.Add(item);
}
I hope it works now.
In theory, everything should work fine - in the inspector, it shows that both of the objects tagged "rbtime" have been recognized. The thing is, the velocity stop is not going for both of them - only one. The objects are identical - here is my code; maybe you could shed some light on the situation.
#pragma strict
import System.Collections.Generic;
public var player : GameObject;
//var prevVelocityx : float = 0f;
//var prevVelocityy : float = 0f;
//var prevVelocityz : float = 0f;
var isStopped : boolean = false;
var rbTimeObjects : List.< GameObject > = new List.< GameObject >();
function Start() {
for (var item: GameObject in GameObject.FindGameObjectsWithTag("rbTime")){
rbTimeObjects.Add(item);
}
}
function Update () {
var controller : CharacterController = player.GetComponent(CharacterController);
if(controller.velocity.magnitude < 1) {
physStop();
} else {
physStart();
}
}
function physStop() {
//var b : GameObject = GameObject.FindGameObjectWithTag ("rbTime");
for(var b: GameObject in rbTimeObjects){
var rb = b.GetComponent(Rigidbody);
if (isStopped == false) {
rb.velocity = Vector3.zero;
rb.useGravity = false;
rb.is$$anonymous$$inematic = true;
isStopped = true;
}
}
}
function physStart() {
//var b : GameObject = GameObject.FindGameObjectWithTag ("rbTime");
for(var b: GameObject in rbTimeObjects){
var rb = b.GetComponent(Rigidbody);
if (isStopped == true) {
rb.is$$anonymous$$inematic = false;
rb.velocity = Vector3.zero;
rb.useGravity = true;
isStopped = false;
}
}
}