Add particles on button click in unity - unity3d

I am new to unity 3d, I have to do some enhancement in exiting project.. if user choose correct option then I have to show some particles around the button at runtime.
My code for adding particles is below ..not working:
ParticleSystem ps = GetComponent<ParticleSystem>();
ps.Play ();
I have also added particles component from unity editor..
Thanks in advance
Edit :
as #kardux suggested:
declaration :
[SerializeField] private ParticleSystem ps;
on method :
ps.Play()
Screenshot from inspector:
Error:
I/Unity (23313): NullReferenceException
I/Unity (23313): at UnityEngine.ParticleSystem.<Play>m__0 (UnityEngine.ParticleSystem ps) [0x00001] in /Users/builduser/buildslave/unity/build/artifacts/generated/common/modules/ParticleSystem/ParticleSystemBindings.gen.cs:3666
I/Unity (23313): at UnityEngine.ParticleSystem.IterateParticleSystems (Boolean recurse, UnityEngine.IteratorDelegate func) [0x00003] in /Users/builduser/buildslave/unity/build/artifacts/generated/common/modules/ParticleSystem/ParticleSystemBindings.gen.cs:3780
I/Unity (23313): at UnityEngine.ParticleSystem.Play (Boolean withChildren) [0x00020] in /Users/builduser/buildslave/unity/build/artifacts/generated/common/modules/ParticleSystem/ParticleSystemBindings.gen.cs:3666
I/Unity (23313): at UnityEngine.ParticleSystem.Play () [0x00005] in /Users/builduser/buildslave/unity/build/artifacts/generated/common/modules/ParticleSystem/ParticleSystemBindings.gen.cs:3661

First of all if you're using particles inside Unity UI I highly advise you looking to UIParticleSystem.cs script from Unity UI Extension repository: this is a community gathering of many useful UI tools :)
(simply don't forget to add the UI/Particles/Hidden shader that you can find here)
You can change the sprite you want to use here:
Also keep in mind when using this script that you will have to scale your particles according to your screen (particles are initialized at a size of 1 because that's 1 meter in Unity 3D world: but now you will probably be in canvas space which will be something like 1920x1080px so 1px will be very small). You can find some base settings below:
Now coming to your scrip I suspect you simply have to call Stop() before Play() like this (note I used a burst emission type in my particle system settings):
ParticleSystem ps = GetComponent<ParticleSystem>();
ps.Stop ();
ps.Play ();
P.-S. Please note that if you use UIParticleSystem script you will have to consider your particles system as an UI item (will be rendered on top of other items based on hierarchy order)
Hope this helps,
EDIT:
You have two ways of setting up your GameObjects:
you have all component on the same GameObject (ParticleSystem, UIParticleSystem and YOUR_SCRIPT): this way you can get the ParticleSystem reference by calling GetComponent<ParticleSystem>() inside your script
you have one particle GameObject (with ParticleSystem and UIParticleSystem) and YOUR_SCRIPT is on another GameObject: you can't call GetComponent<ParticleSystem>() in your script since it will search on the components of this GameObject so you declare a ParticleSystem ps; variable (either public or [SerializeField] private) that you assign through the Inspector by dragging your particle GameObject to it.
Note that implicitly, GetComponent<ParticleSystem>() equals this.gameObject.GetComponent<ParticleSystem>(): that's why it will search components from the current GameObject.
EDIT 2:
Not sure why your script throw this NullReference exception: I just tried with a very short script and it works perfectly...
public class TestScript: MonoBehaviour
{
[SerializeField]
private ParticleSystem ps;
void Start()
{
// This one is not even needed
ps.Stop();
}
public void PlayParticles()
{
ps.Stop();
ps.Play();
}
}

Provided you have a particle system on the same gameObject as the script that is calling it, it should be fine.
Are you using a UI button? If so, have a look here..
http://answers.unity3d.com/questions/852397/particle-system-in-46-ui.html
It's old but still relevant.

Are you using the New Unity UI System or GUI, Is the UI worldspace?
Create a empty gameobject - attach the particle to that.
Whenever you want emit particles call Gameobject.SetActive(true);
Make sure Play on Awake option is checked in the particle system.
Set the position of the particle according to your UI.

public GameObject particle;
//include the particle in the gameobject
void Start() {
particle.SetActive(false);
}
void button() {
particle.SetActive(true);
}
//this works.

Related

How to disable the Tracked Pose Driver in a Unity VR Application?

I need to write a VR application that disables HMD positional tracking for a specific situation and then reenable it again.
In the UI it is a simple as ticking and unticking the TrackedPoseDriver shown in the picture below.
How can I do that via Scripting?
I assume I need to use the enabled property of a game object. But I don't know how to grab a hold of this GameObject (or Component).
EDIT: In case this was clear this is GameObject/Component associated to the main camera.
Ok. So I was able to do It.
What I did is I search MonoBehaviour Based Components on the camera and then cast it to a MonoBehaviour once I found the right one. And then used the enabled property. Like this:
Component[] components = Camera.main.GetComponents(typeof(MonoBehaviour));
bool found = false;
foreach(Component component in components) {
string name = component.ToString();
MonoBehaviour mb = (MonoBehaviour) component;
if (name.Contains(TRACK_POSE_DRIVER_NAME)){
mbTrackingPose = mb;
found = true;
break;
}
}
The unique string that the toString() method provided was somethign like (I don't have it on hand) "Main Camera (Unity.XR.TrackedPoseDriver)". So I just made sure that the string had the "TrackedPoseDriver" and stored that as a MonoBehaviour.
I hope this helps someone else.

How to properly use prefabs from AsssetBundles?

I've recently encountered AssetBundles and tried to implement it in my project. I have a pretty simple game where controlling a character you should collect coins. I created the AssetBundle where I made prefabs and put everything from the game scene (background, player, terrain, etc...) into the AssetBundle. However, when loading objects from the bundle to the game scene, despite having the same size and transform parameters in the inspector, they are bigger than their original prefabs when starting a game. When it comes to the loaded character, not only is it ten times the size of the original but it also needs to be readjusted in script dependencies during the game to control it with a joystick. In terms of prefab size discrepancy, I think it has something to do with the loading screen as everything that comes out of the bundle is scaled to its size (see Fig.1) but I don't know why it happens nor how to fix it.
The script which loads prefabs:
public class LoadAssetBundles : MonoBehaviour
{
AssetBundle loadedAssetBundle;
public string path;
public string assetName;
void Start()
{
LoadAssetBundle(path);
InstantiateObjectFromBundle(assetName);
}
void LoadAssetBundle(string bundleUrl)
{
loadedAssetBundle = AssetBundle.LoadFromFile(bundleUrl);
}
void InstantiateObjectFromBundle(string assetName)
{
var prefab = loadedAssetBundle.LoadAsset(assetName);
Instantiate(prefab);
}
}
Try setting your prefab root (the most outer gameObject) scale to 1, them rescale your sprites inside it.
If you have a CanvasScaler on your canvas, the canvas scale will probably be lower than 1, something small like: 0.02321f, your object seems to have a high scale like 107.f or something, this may be the cause of the discrepancies.
When instantiating, try passing a parent transform (where you want to place your prefab) and change the bool instantiateInWorldSpace (on/off) and see how it affects your prefab.
public static Object Instantiate(Object original, Transform parent, bool instantiateInWorldSpace);
Check docs: https://docs.unity3d.com/ScriptReference/Object.Instantiate.html

Unity3D Text not changing after being set in Start()

I have a Canvas (World Space Render mode) with a Text and a Button component displayed in a tridimensional space (it's a VR app). The canvas instantiated at runtime using a prefab.
I get a reference to the Text object using:
_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent<Text>();
I want to update the text at run-time using:
void Update()
{
_codeTextLabel.text = _codeText;
}
where _codeText is just a variable I update based on specific events.
The problem is that the Text gets updated only the first time, but if I try to change the variable nothing happens. I have tried several combinations and also the method _codeTextLabel.SetAllDirty() but it doesn't work.
The only way to update the text is to re-instantiate the prefab.
Are you instantiating your prefab before setting the values. If you are storing the _codeTextLabel reference before instantiating then your reference will point to the prefab not the runtime object. I can't see the rest of your code, so I can't say for sure. (I would have asked as a comment, but as I'm new I don't have the reputation to do so)
edit: I did a test to try and recreate your problem. I made the following script and it appears to work as expected. CanvasPrefab is a worldspace canvas with a UnityEngine.UI.Text component attached. (The script is attached on an empty game object in the scene btw)
public class ChangeText : MonoBehaviour
{
public GameObject CanvasPrefab;
private GameObject runtimeCanvas;
public string runtimeText = "something";
private Text textRef;
// Start is called before the first frame update
void Start()
{
runtimeCanvas = GameObject.Instantiate(CanvasPrefab);
textRef = runtimeCanvas.GetComponentInChildren<Text>();
}
// Update is called once per frame
void Update()
{
textRef.text = runtimeText;
}
}
as long as you did something wrong, It works absolutely so I guess there are several cases
Failed to do "_codeTextLabel = canvasPrefab.transform.Find("CodeTextLabel").gameObject.GetComponent();"
'_codeTextLabel' lost reference from 'GameObject.
Doesn't change runtimeText' change at all
Subscription of events failed I mean, your updating scripts doesn't get proper event to update that text.
Without codes, this is only thing I can guess for yours so please check above I hope there is case among above.

How to stop NavMeshAgent separating from Animator?

I am working on a research project that uses a NavMeshAgent. I currently have a very simple scene where an agent is spawn at the start, walks through an "entrance" trigger collider, an "exit" trigger collider, then ultimately collides with a "destroyer" trigger collider with a script that ends the scene. Nothing complex, no physics collisions should be occurring.
I've been running some simulations both in the editor and in -batchmode -nographics via an executable that logs a basic runtime statistic when the scene ends. I found that in both the Unity editor and the CLI execution that occasionally the scene's execution time would spike. I finally caught what was happening in action- the NavMeshAgent component was becoming detached from my agent and floating out in front of it.
In this picture you can see the two colliders on the agent (one very small through his body for physics and one larger one for his "personal space",) the exit trigger collider (the giant red box on the right,) and floating between the two is a capsule-shaped NavMeshAgent component.
I used this unity page detailing how to use NavMeshAgents with animators, but after recreating their recommended setup, I am still having the issue.
Does anyone have any solutions for anchoring the NavMeshAgent to the agent itself?
I met exactly the same problem, where making the NavMeshAgent component a child and setting the NavMeshAgent's local position in every frame solved the problem.
private NavMeshAgent agent;
void Awake()
{
agent = gameObject.GetComponentInChildren<NavMeshAgent>();
anim = gameObject.GetComponent<Animator> ();
}
private void Update()
{
agent.transform.localPosition = Vector3.zero;
// todo:
// set animator
}
void OnAnimatorMove ()
{
// Update position to agent position
transform.position = agent.nextPosition;
}
For those of you who stumbled here, but for whom the accepted answer did not work. Make sure that navMeshAgent.updatePosition is set to true or that it is not changed within a script. This could be the cause of the separation.
NavMeshAgent navMeshAgent;
// This may cause the agent to separate
navMeshAgent.updatePosition = false;
// This will make sure it is synced
navMeshAgent.updatePosition = true;
This works as of version 2022.1 of the Unity API. Here are the docs for the function : https://docs.unity3d.com/ScriptReference/AI.NavMeshAgent-updatePosition.html

How do I use SteamVR_LoadLevel to fade between scenes in unity3d?

I've got this at the top,
public GameObject mainCamera
and then I've got this within an if statement,
SteamVR_LoadLevel tempload = mainCamera.GetComponent<SteamVR_LoadLevel>();
tempload.fadeOutTime = 1f;
tempload.fadeInTime = 1f;
tempload.Trigger();
but I'm getting this error when triggering the if statement,
Coroutine 'LoadLevel' couldn't be started because the the game object 'Camera (head)' is inactive!
Edit 1. I figured it out, I should have made the mainCamera variable of type SteamVR_Camera and I should have nullchecked it as well as tested for it being active and enabled.
Check state game object "Camera (head)" in hierarchy window and active him