How Do I Destroy Finished Walking Particle (Clones) in UNITY? - unity3d

VIDEO < in the video I have a walking particles that appear when ever my player moves left and right but I want them to be destroyed after the particles are finished fading away I tried using stop action in unity but that only destroyes the finish particles when the player stops moving and after that the particles will
stop showing up
these are my dublicated particles that will stay in my game forever and cause lag later on I need a way to stop showing them when they are done
IMAGE < the inspector of my particles
image < the name of my particles
is there a way I could some how in my code check if the particle is faded away or check if its finished and then destroy those because sometimes with the destroy it will destroy everything and the particles wont show up if I walk again
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class partscript2 : MonoBehaviour
{
public Joystick joystick2;
public GameObject hays2;
public Rigidbody2D rb;
float horizontalMove = 0f;
// public bool show = true;
public Animator animator3;
// public Transform player;
//public Transform particleposition;
// Start is called before the first frame update
void Start()
{
//transform.position = particleposition.position;
animator3 = GetComponent<Animator>();
//Destroy(gameObject, 1f);
}
//destroy(hays);
// Update is called once per frame
void Update()
{
if (joystick2.Horizontal <= -.2f)
{
Instantiate(hays2, transform.position, hays2.transform.rotation);
}
if (joystick2.Horizontal >= .2f)
{
Instantiate(hays2, transform.position, hays2.transform.rotation);
}
}
}

Firstly, instantiating a game object in update is not the best way to go considering that if your game runs at 60 frames per second you will end up creating 60 game objects each second which can and most likely will affect performance especially on a mobile device which you are working.
But into the point, you can call the Destroy method and pass the duration of the particle.
GameObject hay = Instantiate(hays2, transform.position, hays2.transform.rotation);
ParticleSystem p = hay.GetComponent<ParticleSystem>();
float duration = p.duration + p.startLifetime;
Destroy(hay , duration);
If your particle's duration is fixed you can always skip the part where we get the duration via script and simply pass it in the Destroy method.
GameObject hay = Instantiate(hays2, transform.position, hays2.transform.rotation);
Destroy(hay , 5f);

Related

Better movement script needed?

I got an issue that I've been trying to figure out for some time now and still haven't managed. I created a script for movement which besides using the WASD keys also uses two more buttons to go up and down. The thing is - because of the way I added those buttons for some reason no other function regarding position of the player doesn't work well. For example if I put a collider with a simple on trigger transform.position function for the player to hit - the player is placed on that position but then instantly returned back like there was nothing.
Here is my code. I had tons of iterations how this movement can be done. I did it through physics and controller in several ways but nothing helped. Can you guys tell me if it's the code or some hidden Unity synergy that I don't know about?
(this version works around addForce. Regardless, whatever way I make the up and down functions I cannot move the player with script after that.)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Mov : MonoBehaviour
{
private CharacterController controller;
private Rigidbody Rb;
private Vector3 playerVelocity;
private float playerSpeed =12;
void Start()
{
controller = gameObject.AddComponent<CharacterController>();
Rb = gameObject.GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate()
{
Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Vector3 add =new Vector3 (0, playerSpeed, 0);
controller.Move(move * Time.deltaTime * playerSpeed);
if (Input.GetKey(KeyCode.Mouse1))
{
Rb.AddForce(0, 1200, 0, ForceMode.Acceleration);
}
if (Input.GetKey(KeyCode.Mouse0))
{
Rb.AddForce(0, -1200, 0, ForceMode.Acceleration);
}
}
}
I'm not sure what you mean by "no other function regarding position of the player doesn't work well" but from have you turning "Collision Detection" in your Rigidbody's settings to "Continuous" and "Interpolate" to "Interpolate"? If you don't do so, Unity's collision's may be a bit funky especially if you are going at high speeds.

how can i fix "GameObject has been destroyed but you are still trying to access it" - unity

I am in process to make a 3D fps game with unity. But when i wrote the code to destroy the bullet after a particular time say - 5 seconds, till 5 seconds it spawnes the bullet and after 5 seconds the bullets spawned bullets get destroyed. But after that when i try to again spawn bullets, they dont get spawned and it shows the error GameObject has been destroyed but you are still trying to access it.
here is the destroy bullets code
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
public class Bullet : MonoBehaviour
{
public float speed = 8f;
public Camera playerCamera;
public float lifeDuration = 2f;
private float lifeTimer;
void Start()
{
lifeTimer = lifeDuration;
}
// Update is called once per frame
void Update()
{
transform.position += playerCamera.transform.forward * speed * Time.deltaTime;
lifeTimer -= Time.deltaTime;
if (lifeTimer <= 0f)
{
Destroy (gameObject);
}
}
}
I believe that when you destroy the GO, the reference to that object may be lost too. In your case, in which you're using bullets, I recommend you to instead of using Destroy(gameObject), use gameObject.SetActive(false) and recycle the bullets with a pool of bullets that you instantiate at the start of the game. That way is easier to have a reference to the GO and optimize the cost of instantiating x bullets.
This error occurs when you try to access a gameobject which has been destroyed.
how do you spawn the bullet?
if it's a prefab,i suggest you do like this,and DO NOT call this gameobject in any other script after its "lifeTime":
var go = GameObject.Instantiate( Resources.Load( "bullet prefab path" ) ) as GameObject;
go.AddComponent<Bullet>();
if not, i think you're Instantiate a gameobject already exist in Hierarchy.
//if the "prefab" is already exist in Hierarchy with script "Bullet" and is active
//this "prefab" will be destroyed by your bullet script after "lifeTime"
//when the next time you Instantiate() with this "prefab"
//you'll get the error:"GameObject has been destroyed but you are still trying to access it"
GameObject go = GameObject.Instantiate(prefab) as GameObject;

How to add a spawner on a side of moving camera in unity2D

I'm creating a 2D racing game in Unity2D and unsure how to approach on coding my spawner for objects e.g. power-up, rewards and obstacles ahead on the right side of my moving camera. The camera follows my vehicle and moves from left to right. Currently objects spawn in the game, but only spawn on a point and continue to spawn in the same point when the camera has scrolled way past. Apologies, if the answer was simple.
Here are the scripts I used:
coin.cs is attached to my coin prefab
public class coin : MonoBehaviour
{
public Camera mainCamera;
Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
mainCamera = GameObject.FindObjectOfType<Camera>();
rb = this.gameObject.GetComponent<Rigidbody2D>();
transform.position = new Vector2(mainCamera.pixelWidth / 32, getRandomHeight());
}
float getRandomHeight(){
return Random.Range(-(mainCamera.pixelHeight / 2) / 100, (mainCamera.pixelHeight / 2) / 100);
}
private void OnTriggerEnter(Collider coll){
if (coll.gameObject.tag == "Player"){
Destroy(this.gameObject);
}
}
// Update is called once per frame
void Update()
{}
}
and coinSpawner.cs is attached to a gameObject in the scene
public class coinSpawner : MonoBehaviour
{
float LastSpawnTime = -500f;
float NextSpawnTime = 3;
public Object CoinPrefab; // declare coinPrefab
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Time.time - LastSpawnTime > NextSpawnTime)
{
NextSpawnTime = Random.Range(3, 10);
LastSpawnTime = Time.time;
Instantiate(CoinPrefab);
}
}
Instantiate(CoinPrefab);
spawns this object without any information of position or parent object. This it will always be spawned at Scene root and 0,0,0.
Then this line
transform.position = new Vector2(mainCamera.pixelWidth / 32, getRandomHeight());
in coin always places it to the absolute position depending on your pixelWidth which doesn't change over time.
You are saying the Camera is moving so you should rather take it's transform.position into account.
You have basically two(three) ways to go here:
You can make the spawner GameObject a child of your Camera - so it is automatically moved along with it - and move it to the right to have the desired offset. Then simply spawn new objects at this GameObjects position. Then you can do it in coinSpawner:
Instantiate(CoinPrefab, transform.position, Quaternion.Identity);
Or get the Camera reference and use it's position + the desired offset either also only in coinSpawner like
// reference this already via the Inspector if possible
[SerializeField] Camera _camera;
// Otherwise get the reference on runtime
void Awake()
{
if(!_camera)_camera = Camera.main;
}
float getRandomHeight => Random.Range(-(_camera.pixelHeight / 2) / 100, (_camera.pixelHeight / 2) / 100;
and then do something like
Instantiate(CoinPrefab, new Vector2(_camera.transform.position.x + mainCamera.pixelWidth / 32, getRandomHeight()), Quaternion.Identity);
This would actually be more efficient since the entire coin script would be reduced to only the OnTriggerEnter part and not every coin would use FindObjectOfType and GetComponent when spawned.
Basically the same as above but sticking to your code structure simply do
transform.position = new Vector2(mainCamera.transform.position.x + mainCamera.pixelWidth / 32, getRandomHeight());
I wouldn't do it this way though due to efficiency as said.

Camera follow player around planet

I have a planet and a player moving on it using gravity. I would like to have a camera to follow the player around it. Using the Parent Constraint component works perfectly, but I want to delay the rotation follow, so I have to use a script. I just cannot figure out how to make it follow it around the globe. I either have a camera that completely freaks out, or a camera that sort of follows the player but doesn't move over the planet and always stays in front of it. And often the position following works, but as soon as I add something that changes rotation it only does that. I've tried many different scripts but nothing works. I'm grateful for any help.
EDIT
I'm sorry for not adding an example. At the moment I've tried this script attached to the camera:
public class CameraFollow : MonoBehaviour
{
public GameObject player;
private Vector3 offset;
void Start()
{
offset = transform.position - player.transform.position;
}
void LateUpdate()
{
transform.rotation = Quaternion.Slerp(transform.rotation, player.transform.rotation, 50f * Time.deltaTime);
transform.position = player.transform.position + offset;
}
The camera does mimic the rotation of the player, but the position isn't being follow correctly anymore. It seems mostly stuck in place, moving only very slightly.
In order to have a camera following a GameObject, you need to go to the camera you want following the GameObject, select Add component, write FollowPlayer, press New script, and then press select and add. Edit the script so it contains the following:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowPlayer : MonoBehaviour
{
public Transform player;
public Vector3 offset;
// Update is called once per frame
void Update()
{
transform.position = player.position + offset;
}
}
Then, you will need to drag and drop the GameObject you want the camera to follow, in the "Player" box.
Define the offset of the camera from the GameObject, and your'e good to go.

how to add gaze input timer to trigger an action after gazing for 3secs?

I am new to unity and VR. I have been using google cardboard SDK to create VR apps in unity and am stuck at gazetimer. I want to trigger an action only if the user looks at any object for 3secs but have not been able to do so. Please help
Please see a similar question and answer here Use Gaze Input duration to select UI text in Google Cardboard
In summary, create a script to time the gaze, by cumulatively adding Time.deltaTime on each frame when the object is gazed at. When gaze time hits a pre-specified duration, trigger the button's OnClick event.
On the object, activate the script's gaze timing functions using event triggers Pointer Enter and Pointer Exit. See screenshot:
VR Camera usually contains a main camera and eye cameras (right and left). Since Main camera's center point will always be the center of the eyes of the user's point of view, you could use Raycast from its transform.position to its transform.forward and check whether it hits your object. Then simply add a timer which will call the action after it reaches the duration you have set.
For example:
using UnityEngine;
using System;
[RequireComponent(typeof(Collider))]
public class LookableObject : MonoBehaviour {
[SerializeField]
Transform cam; // This is the main camera.
// You can alternately use Camera.main if you've tagged it as MainCamera
[SerializeField]
float gazeDuration; // How long it should be gazed to trigger the action
public Action OnGazeAction; // Your object's action after being gazed
Collider gazeArea; // Your object's collider
float timer; // Gaze timer
public void Start () {
gazeArea = GetComponent<Collider> ();
}
public void Update () {
RaycastHit hit;
if (Physics.Raycast (cam.position, cam.forward, out hit, 1000f)) {
if (hit.collider == gazeArea) {
timer += Time.deltaTime;
if (timer >= gazeDuration) {
if (OnGazeAction != null)
OnGazeAction ();
}
} else {
timer = 0f;
}
} else {
timer = 0f;
}
}
}
Hope you get the idea.