How do I acess a script (or in my case rigidbody/collider) in a complex child-hierarchy, when the script is placed on mutliple gameobjects?
I want to call a function to set all the respective colliders to off with one click. The problem is, the colliders are placed on different gameobject within the RightHandController. The idea was to target the RightHandController, iterate down somehow and check if a colliders is attached and if so, disable it (see picture). Is there any good way to do this?
Related
Hello I am having a problem and I dont know how to solve it.
I want to create a 3d puzzle where the player needs to move multiple 3D objects to put them together. I already know how to implemet the movement (LeanTouch) but I need a way to recognize when two objects touch each other in special places. Then I would use transform to combine them. Does anyone have an Idea how to solve this?
One way to solve this is to create child objects with the colliders in the specific places you want to detect collision at. Then in OnCollisionEnter() you can practically combine them by creating a new parent of the two objects. Here's an example of an approach I took:
I set up my colliders like this:
Then on the individual colliders I added this code. Front is just the tag attached to the collider shown in the hierarchy.
void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Front"))
{
var newParent = new GameObject();
newParent.transform.SetParent(collision.transform.parent.parent); // Get the parent of the current gameobject the collider is attached to
collision.transform.parent.SetParent(newParent.transform); // Doing .parent because this is the child collider
transform.parent.SetParent(newParent.transform);
}
}
It's not perfect, but the result is that the objects were combined under the same parent.
Alternatively, you could simply make one cube the child of the other by removing NewParent and replacing it with collision.transform.parent.
You should probably use colliders for that, and then use the collision event
I am making a simple inventory/equipment system with a basic square character. One of the items you can use is a potion that will increase the pickup item area. I have a way to do this already, but I am wondering if there is a better way to do this?
WHAT I CURRENTLY HAVE
I have a collider on my character object, which deals with collisions with the walls and general world (all this handled in the Player script).
I then have an empty gameObject child of this object, which has a collider component the same size as the other collider (at start).
The child gameObject has a script (PickupAreaModifier script) with a OnTriggerEnter2D function that calls a method in the main character script to add the item.
If the item is the potion, then the Player script calls a method in the PickupAreaModifier script to change the size of that collider.
WHAT I WANT
This current logic works, but I would like to know if there is a more efficient way to handle this, especially considering the OnTriggerEnter2D function needing to be called on the child gameObject script. Is there any way I can handle this in only the Player script?
Thank you in advance, I hope that makes sense!
I want to use a single script to control all elements of one scene. Let's call it "Director" script, bound to EventSystem.
I knew that I can get a GameObject by name or tag, and then manipulated the components such as transform. Thus I wondered if I can define the OnTrigerCollider2D() in this "Director” script without binding any script to the Collider2D GameObject, just like I define the value of the transform? If possible, how?
According to some friend, it is necessary to bind at least a basic script to the Collider2D to authorize the "Director" script to get access to the Collider2D event, no way to bypass this limitation?
From the docs:
MonoBehaviour.OnTriggerEnter2D(Collider2D)
Sent when another object enters a trigger collider attached to this
object (2D physics only).
Further information about the other collider is reported in the
Collider2D parameter passed during the call.
In order for the event to fire, the trigger collider must be attached to the same object as your behavior. Using a small script on the object with the collider with a reference to call a method on your "Director" is the most common way I've seen this done. As far as I know, it's impossible for objects to "subscribe" to collision events fired by other objects.
A poster here suggests that one solution could be to create a collision manager that the "Director" checks, but the objects actually having collision events would need to notify the collision manager, so with that solution you're just adding a step. Depending on what you actually want to do with collision events, it might make sense for you though.
Example
In Unity5, assuming that a GameObject with name "SomeObject" was stored as a prefab at Assets/Resources/SomeObject.prefab, I know that I can create an instance of the prefab as follows:
GameObject prefab = Resources.Load<GameObject>("SomeObject");
GameObject instance = GameObject.Instantiate(prefab);
Once executed, the instance GameObject will be a copy of the original "SomeObject" prefab, and will have been placed in the current active scene with the name "SomeObject(Clone)".
As far as I understand, the GameObject prefab represents the actual prefab asset, and any changes made to it (setting name, adding components, etc) are written to the original prefab asset, and these changes persist even after exiting editor play mode.
Questions
Since all GameObjects are normally stored in a scene, and the scene property on GameObject prefab in the above example seems to be Unloaded/Invalid/Unnamed, where exactly should I consider this special GameObject to be? I seem to be able to do everything with it that I can do with normal GameObjects, short of being visible in the hierarchy/scene view.
Is it effectively in some kind of limbo state, or a special PseudoScene? It seems to persist through LoadSceneMode.Single scene changes, but is not like the special DontDestroyOnLoad scene that Objects are moved to when passed into GameObject.DontDestroyOnLoad(...).
Are there any other noteworthy differences between prefab and instance in the above example, other than lifetime changes, the invalid scene and being different objects from one another (Having different GetInstanceID(), etc)?
Since calling GameObject.Instantiate(...) on prefabyields a GameObject that is in a valid scene, is there any way to manually create GameObjects that are in a similar 'no scene' state? I am aware that Unity intends for all GameObjects to be in scenes and so this is purely an academic question.
I have tried looking through the documentation of the functions involved, but none go into the technical details of what specifically is happening when you call Resources.Load on a prefab resource.
1.Where exactly should I consider this special GameObject to be?
It's in a separate file and not referenced in the scene. Once Resources.Load<GameObject>("SomeObject"); is called, it is loaded into the memory waiting to be used when GameObject.Instantiate is called.
If it is declared as public GameObject prefab; and assigned from the Editor instead of GameObject prefab Resources.Load<GameObject>("SomeObject");, it will be loaded into the memory automatically when the scene loads.
2.Are there any other noteworthy differences between prefab and object?
Yes.
Prefabs cannot be destroyed with the Destroy or DestroyObject function. It has to be destroyed with the DestroyImmediate function by passing true to its second arguement: DestroyImmediate(prefab, true);
3.Is there any way to manually create GameObjects that are in a similar 'no scene' state?
No, there is no way to manually create GameObjects that are in a similar 'no scene' state.
Although you can fake it.
The closest thing to that is to make the GameObject invisible in the Editor's Hierarchy and Inspector tabs by modifying the GameObjects's hideFlags variable then deactivate that GameObject.
GameObject obj = new GameObject("SomeObject");
obj.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
After that, deactivate the GameObject:
obj.SetActive(false);
Now, the GameObject is invisible in the Editor and it is also invisible in the Scene and Game View.
There is really no big difference between prefabs and a typical GameObject. Prefab is just a container that holds the GameObject so that it can be re-used and shared between scenes. Modifying one prefab will update any instance of it.
Imagine when you have hundreds of GameObjects of the-same type in the scene and need to modify all of them. With prefab, you only need to modify one of them or just the prefab then click Apply to update other instances. This is the only thing you should think of prefabs.
How do I detect Input.GetMouseButtonUp outside a specific GameObject's area in Unity? Are there any Unity Assets for this, or should we do this programmatically?
It certainly has to be done by programming it, whether there is an asset or not. As it is rather easy to program, I doubt there is one.
What you need to understand is, that Input.GetMouseButtonUp(int button) is an event and entirely decoupled from any "position". The description from the API says "Returns true during the frame the user releases the given mouse button.".
So in the frame a mouse button has been released you want to check if the arrow is "touching" or laying over some GameObject (GO). According to your example you will do nothing when the GO was hit, and else do something.
One way to do that is to use the following method:
http://docs.unity3d.com/ScriptReference/Camera.ScreenPointToRay.html
Your GameObject will at least need a collider, maybe a rigidbody too in order to be detected by the ray. I'm not completely sure atm if both are needed.
Additional note: Having an UI element, this method could also be used to set some flag while hovering over it e.g. : http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseOver.html