Newbie component questions.

Hi all,

Have searched on this but am confused :slight_smile:

I simply :slight_smile: which to access a variable from other script.

Thus I have:

public Rigidbody bodyhit = null;
etc…
bodyhit = hit.collider.attachedRigidbody;

I wish to access ‘body hit’ from another script and have:

private static Contact contact;

// Use this for initialization
void Start ()
{
contact = (Contact) GetComponent(typeof( Contact ));
}

// Update is called once per frame
void Update ()
{
Debug.Log(“contact:”+contact);

if (contact)
if (contact.bodyhit)

etc.etc.

But contact.bodyhit is always null. Do I need to reference the external variable by class or Gameobject?. I assume my basic principal is right!! :-)))

Any help appreciated

thanks

Here is a simple list of objects you ordinarily access in Unity:

gameObject
transform
rigidbody
collider
renderer

So each of these is an object. As a matter of fact, almost everything in Unity is an object, linked in some form or fashion. A transform is the object of a gameObject that controls position, rotation and various other things. A rigidbody is actually a component. (A component is an object that is attached to another object)

So to help you go down the right direction… Everything in Unity is an object. This includes scripts.

So lets look at this script:

//myCar.cs
using UnityEngine;
using System.Collections;

public class myCar : MonoBehaviour {
	public Rigidbody bodyhit = null;
}

We can see the script is named “myCar” and extends the MonoBehaviour class. All classes are effectively un-created objects. So in order to create the object we need to attach it to something.

lets make a cube, with 4 sphere on it’s corners, and we will attach this script to the cube. Lets just call the cube… “car” just for the fun of it.

The cube will need a rigidbody, so we need to attach one to it.

Now, lets look at the spheres… and for the fun of it lets call them "wheel"s. Each “wheel” needs a collider, so lets use the WheelCollider. (imagine that) Next, lets get some script on each wheel.

//myWheel.cs
using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
	void FixedUpdate() {
		Vector3 forward = collider.attachedRigidbody.transform.forward;
		collider.attachedRigidbody.AddForceAtPosition(forward, transform.position);
	}
}

Again, this script is called “myWheel” and extends the MonoBehaviour class. And, again, we need to attach it to each wheel to make it work.

In the case of the wheel, every physics cycle (FixedUpdate) each wheel is going to apply force to the car, but only at the point where the wheel is. This is going to mimic what real wheels do.

OK, what makes this special, and why do we care? Well, in the FixedUpdate method, we are creating a vector from a collider. How do we do this? Objects… First, the collider is an object. It has certain methods that help us handle things. One of those things is a property called “attachedRigidbody”. This is a pointer to an object… which is the rigidbody that we are currently attached to. This rigidbody is somewhere in the hierarchy of this object. Generally it is on the same object, or just above it in the stack. This means that by using collider.attachedRigidbody, we gain access to the Rigidbody that is held there.

Now… Rigidbody is much like the collider in that it has lots of pointers to other objects, as well as it’s own set of properties and methods. One of these pointers is to a thing called “transform”. This allows us access to the Transform attached to the same object that the rigidbody is attached to. This is the positioning of the car’s body. The Transform also has its own set of stuff… and we continue on…

OK, now, lets consider that the script “myCar.cs” is an object. The script can be attached by dragging it to the model or inspector to attach it because it extends the MonoBehaviour class. (Yes, this is VERY important)

Now, because it is attached to the car’s GameObject, we can access it by using some of the methods in the GameObject … object.

The exact method is "GetComponent(). To access it, we need to fill out the generic …

ScriptName other = gameObject.GetComponent<ScriptName>();

So, now lets answer your question. “How do you access a property, component or method of a class, from outside the class, IF that class is a MonoBehaviour derived class?”

Rigidbody bodyhit = gameObject.GetComponent<myCar>().bodyhit;

And better still…

Rigidbody bodyhit = collider.attachedRigidbody.gameObject.GetComponent<myCar>().bodyhit;

Now, you can see where object to object, we get a link from the current active collider, to the rigidbody that it is attached to, then to the game object it is attached to, then finally to the script we are using and lastly to the property “bodyhit”.

Hope this helps.

Hi

Firstly thank you for your very detailed reply and patience -it is appreciated :slight_smile:
Whilst I get most of what your saying I am still confused by which object should take responsibiliy for a script when that script might not have any obvious link to the object. Wheels, to rigid body to collider to car body is all fine and logical , perhaps the issue is the way I organise my objects.
At the moment I have attached a script to my player that is called collider and deals with collisions, I assume I could attach that script to all objects that need collision dealt with ?
But I wish maybe another object to know if a completely different object has collided.
So how can A know about B when neither are parent/child of the other ?

Forgive my newbie’ness :slight_smile:

Again I really appreciate your help in my understanding.
I did try and look at the angrybots code ; but erm , I get well lost - can’t even see how collisions are resolved in that I.e what object calls damage health object

Thanks again in advance

First, refrain from creating scripts named the default names in Unity. that can be a bad thing. so a script called “collider” or “Collider” would be the same name as an existing object in Unity. (I know, how do you know? Reading the documentation would help and finding out what things are named)

OK, If object A has a collider and you it hit’s object B’s collider… Then it would create an event called OnCollisionEnter on both of them.

The collision information passed lets each object know what the other is. It may however not know the hierarchy of them.

Consider this:

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
	void OnCollisionEnter(Collision collision) {
		ContactPoint contact = collision.contacts[0];
		Debug.Log(contact.thisCollider.gameObject.name + " hit: " + contact.otherCollider.gameObject.name);
		if(contact.otherCollider.attachedRigidbody)
			Debug.Log(contact.otherCollider.gameObject.name + " has a rigidbody on object: " + contact.otherCollider.attachedRigidbody.gameObject.name);
	}
}

When placed on an object, and it hits, or another object hits it, it will print up to two lines. The first line recognizes the hit and what collider it hit. The second line will post the name of the rigid bodies’ object. Thus giving you both objects involved in teh collision, and the third object which “should” be the base object in the hierarchy. (I say should, because it is not always the case where the rigidbody contains all of the scripting that controls the object. It would be nice to be consistent.)

Hey BigMisterB,

That’s great appreciate the info.

Thanks