If a GameObject will be activated and deactivated, should it be static? - unity3d

Say you have some GameObjects which are using Render Mode: Screen Space - Camera. These will be hidden and shown via activation and deactivation. Are they to be considered Static, or no?

In order to activate or deactivate a GameObject it doesn't matter if it's static or not. Unlike a dynamic GameObject a static one has disabled movement
at runtime but it doesn't lock its active state. At least that is my case.

Related

World space button click event to take priority over the collider's click event it's inside?

Short story:
I have a button on a world space canvas with a click event handler. This is inside (in 3d space not parenting) of a 3d collider with it's own click event.
The collider always gets the click event as expected as it's nearer the camera.
I want the button to get the event.
Long Story:
I have a person mesh with a collider. You can click on them and the OnPointerClick triggers to do something.
I have a button that sits in a world space canvas which itself is located just above the mesh and is pointed towards the orthographic camera. You click on the coin and the OnClick event triggers to do something else.
Both events work as expected until the coin is inside the mesh's collider (which it is a lot of the time). At which point it's ONLY the mesh collider's OnPointerClick event triggers, not the button.
However, I ALWAYS want the button to take priority over the collider, and any other collider. This is easier when the canvas is screen space, but it's not (with reason).
How do I do this?
NOTES:
The button never gets the onclick event, so any filtering on the containing collider won't help
I've fiddled with the world space canvas and camera ray filtering settings to no effect.
The coin has to be a world space canvas for automatic tracking and because I use text too
IsPointerOverGameObject doesn't help as it's true for any collider, not just UI elements. Not to mention it wont stop the collider consuming the click anyway. A custom version of this that works via a layer wont help either, because again the OnPointerClick on the collider GO stil consumes the click.
I don't want either event to have to do any event filtering & passing on if possible, they should be atomic. Any filtering should be via setting properties in objects and inherent functionality of Unity if possible
Just to reiterate, writing a function to find all objects in the ray and then selecting ones that are on the UI layer first wont help. Because that does not change the fact that the collider still is the only thing that gets the event, which then you'd have to manually propagate down to the button.. which I don't want to do.
I've been able to fix this by putting the button's world space canvas on a sorting layer of 1. That way, even if it's behind colliders, it will register first.
Nice and clear solution that I was hoping would exist.

Unity: I can not access to GameObject.SetActive() if there is an Animation that modifies it?

I am new in Unity and I don't know if I am missing something. I have found this problem repeatedly.
I have a GameObject that I deactivate/activate by code.
The same GameObject is deactivate/activate by animation(s).
Well, this doesn't work.
My commands in code are ignored. Even if the animation is not active right now.
It is easy to see when I am having this issue because while game is in Play I can not modify the active state of the GameObject from the Inspector. Only if I pause the game I can modify the active state in the Inspector but after un-pause the element go backs to the previous state.
I understand that the animation can override whatever is said in code. But I asume that this should happen only when the animation is active.
How can I play with the SetActive() of one GameObject in the animations but also in the code?
In general: You shouldn't mix changes via the animator with runtime changes via script.
It is very easy to lose the overview and you will not anymore know which changes happened because of the animator and which because of a script.
If this is really necessary you should rather use parenting and do e.g.
SomeParent
|-- SomeChild
and either control the SomeParent via the script and the SomeChild via Animator or the other way round.
As soon as there is an Animator where any animation state holds only any keyframe on a certain property, the Animator "locks" that property against any changes via script since the Animator is executed almost latest within one frame.
Try doing your change in LateUpdate or via Coroutine via yield return new WaitForEndOfFrame(); which would be executed after the Animator.
Or if possible you could disable the Animator for the time where you want to "manually" overwrite the property via script like
_animator.enabled = false;
theObject.SetActive(false);

Collisions between UI elements in Unity

I am able to detect collision between UI components and a gameobject if my canvas is rendered in the world space. Here, I am trying to find collision between two UI elements (say UI buttons) when the canvas render mode is screen space overlay.
I added box collider components to my UI buttons and tried using OnCollisionEnter2D and OnTriggerEnter2D. But, the collision is not detected. Is there a way to detect the collision?
The question does not require a code body. However, I have figured out a solution. TO both the UI elements, you need to:
Attach a rigidbody2d component
Attach a box collider component
disable gravity
enable the isTrigger checkbox.
Now in the script attached to one of the UI elements:
void OnTriggerEnter2D(Collider2D other)
{
Debug.Log ("Triggered");
}
This would detect the collision.

Unity particle system only plays if i hit SIMULATE button

I have a prefab with a particle system attached. In the code I play the particle by using this code
ps.enableEmission = true;
When i run the game, and that code executes, the particle emitter does not emit anything in the "game" window unless i press simulate button in the "scene" window.
Anybody knows why?
For the emission property to work the particle system has to actually be playing. To do this you can either enable Play On Awake in the ParticleSystem component or you use the Play method on an instance of the ParticleSystem component.
As a side note, if you are using 5.3+ the enableEmission property is now obsolete and you may want to consider using the emission property. One thing to keep in mind when using this property is you have to assign it to a variable before attempting to modify it:
public ParticleSystem _ps;
...
private void Update()
{
ParticleSystem.EmissionModule module = _ps.emission;
module.enabled = true;
}
UPDATE #1
In response to your tractor beam example in the comments I would probably suggest using SetActive on the game object that has the ParticleSystem component. By using SetActive it will prevent extra particles being emitted and will destroy any that are active, i.e. those currently in the scene.
If you use the Emission property, then it will prevent the emission of extra particles, but it will not destroy any that have already been emitted.
One other approach would be to use Play and Stop methods but these, as with the emission property, will not destroy any active particles. If you use these methods, then some things to watch out for are:
If the Prewarm option is not enabled, then Play does not start
emitting particles (not sure why this happens)
The isPlaying property will remain true as along as there are
active particles in the scene. Once these die, then it will
be set to false
The Stop method will not destroy particles active in the scene
If the ParticleSystem has stopped and you call Play while there are particles active
in the scene, then all active particles are destroyed and the
ParticleSystem starts emitting a new set of particles
Check out to see if particle GameObject is active when you call ps.enableEmission = true; on it. To show or hide particles i normally use gameObject.setActive() not ps.enableEmission.
My particle was not simulating and after I changed the culling Mode to Automatic everything worked. The default is pause and catch-up.

How to change cameras in Unity based on camera coordinates?

I'd like to create a movie in Unity, so I would need several cameras and camerapaths.
On the top of this off course I'd like to change between them. For example if Camerapath1 reaches a significant point with Camera1 then I'd like to change to Camerapath2 with Camera2, etc.
I also have Camera Path Animator asset installed. It's working perfectly when I'm using it with only one camera for several camerapaths but I'm unable to change between maincameras.
I'm a newcomer to Unity. I also know that I should do something like this:
...
camera1.camera.active = false;
camera2.camera.active = true;
...
...but where should I populate these lines? On the top of this, how may I catch the event when a camera on a specific camerapath reaches a particular point?
The way to go would be an animation controller that has all camera as children and controls the active state of all cameras. This provides perfect control over the behaviour.
Create an empty game object, add all cameras as children, add an Animator to the main object with one animation. This animation takes all the camera and set their active state. One extra bonus of this approach is the possibility to call methods as well using the AnimationEvent process. You can still define within the animation for some triggered actions like explosions or movements of objects.
As I said, this give you perfect control since you can define easily actions at specific time.
The downside of it is the rigidity of the process. It may not be as flexible as code, but since you are making a movie, you probably do not need flexibility.
If so, you would have your cameras with a collider and rigidbody (isKinematic true), then you would have some trigger box with a simple script:
public void CameraTrigger:MonoBehaviour{
public GameObject nextCamera;
void OnTriggerEnter(Collider col){
if(col.gameObject.CompareTag("Camera")){
col.gameObject.SetActive(false);
nextCamera.SetActive(true);
}
}
}
Then you drag the camera meant to start next as nextCamera.