I'm having trouble creating a way to check if the Player is NOT colliding with a certain 'waypoint' if I click that waypoint. I've set up 7 waypoints which the player will want to be able to move to.
Now I'm trying to write a piece of script that checks that AFTER the waypoint is clicked (onMouseDown) if there's a collision with the player. Because if that's the case it won't calculate the position to move to.
public class WayPointPositioner : MonoBehaviour {
private Vector3 wayPointPosition;
public GameObject playercheck;
//Check if object is clicked
void OnMouseDown ()
{
Debug.Log ("Object Clicked " + GameObject.name);
// Check if collision occurs with playercheck
OnCollisionEnter(playercheck != Collision)
{
// If its the player, then return a new position for the player to move to for walking
// Else debug that its not so
if (playercheck.gameObject.CompareTag("Player"))
{
Debug.Log ("Object not colliding and retrieving position");
wayPointPosition = new Vector3 (GameObject.X, GameObject.Y, 10);
wayPointPosition = Camera.main.ScreenToWorldPoint(wayPointPosition);
}
else
{
Debug.Log ("Object is colliding, no movement needed");
}
}
}
}
Now I've already figured out that OnCollisionEnter will not work. Because it requires the void-statement before it for it to function. However I have no clue how else I am able to do this.
I would just compare the position of the player and the way point. If equal then the player is there otherwise move to the way point. Hope I understand the problem right.
Managed to fix it. Was just being an idiot.
Key is to use both functionalities, SEPERATELY. So I divided the tasks of checking for Mousedown and checking if the place is occupied by creating a seperate variable to ask true of false from to check it all.
public class WayPointPositioner : MonoBehaviour {
private Vector3 wayPointPosition;
private bool checkPlayerWaypointCollision;
void Start()
{
wayPointPosition = transform.position;
}
void OnTriggerStay2D (Collider2D other)
{
if (other.gameObject.name == "Player")
{
checkPlayerWaypointCollision = true;
}
else
{
checkPlayerWaypointCollision = false;
}
}
//Check if object is clicked
void OnMouseDown ()
{
// If its the player, then return a new position for the player to move to for walking
// Else debug that its not so
if (checkPlayerWaypointCollision == false)
{
Debug.Log ("Object not colliding and retrieving position");
transform.position = new Vector3 (transform.position.x, transform.position.y, 10);
wayPointPosition = Camera.main.ScreenToWorldPoint(wayPointPosition);
}
else
{
Debug.Log ("Object is colliding, no movement needed");
}
}
}
Related
I want to respawn object at a new position immediately after player collides with it.
For now my code just spawn the object after respawn time and destroy the previous object.
The code on my empty object on unity2d is
public GameObject point;
private Vector2 screenBounds;
public float respawnTime = 10f;
GameObject star;
void Start()
{
screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
spawnStar();
StartCoroutine(starWave());
}
public void spawnStar()
{
Debug.Log("Yeah it works");
star = Instantiate(point) as GameObject;
star.transform.position = new Vector2(Random.Range(-screenBounds.x, screenBounds.x), Random.Range(-screenBounds.y, screenBounds.y));
}
IEnumerator starWave()
{
while (true)
{
yield return new WaitForSeconds(respawnTime);
Destroy(star);
spawnStar();
}
}
And the script on object prefab is
void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.tag == "Player")
{
Debug.Log("this is star collider destory");
Destroy(this.gameObject);
}
}
Spawner script
public GameObject point;
void Start()
{
spawnStar();
}
public void spawnStar()
{
Debug.Log("Yeah it works");
star = Instantiate(point) as GameObject;
}
Prefab script
// how long before our star moves
private timeBeforeMoving = 10f;
// our current time
private currentTimer = 0.0f;
// the screen size
private Vector2 screenBounds;
void Start()
{
screenBounds = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, Camera.main.transform.position.z));
transform.position = GenerateNewPosition();
}
private void Update()
{
// increase the time that has passed
currentTimer += Time.deltaTime;
// we have reached the timer threshold, so move the star
if(currentTimer >= timeBeforeMoving)
{
MoveOurStar();
}
}
void OnTriggerEnter2D(Collider2D col)
{
if (col.gameObject.tag == "Player")
{
MoveOurStar();
}
}
private void MoveOurStar()
{
// reset the timer as we just moved
currentTimer = 0.0f;
transform.position = GenerateNewPosition();
}
private Vector2 GenerateNewPosition()
{
return new Vector2(Random.Range(-screenBounds.x, screenBounds.x), Random.Range(-screenBounds.y, screenBounds.y));;
}
Instead of destroying it run your randomize position code again. If you do not want it spawning in the same location as the player, you can use a circle cast to determine if the new location the object will spawn is still on top of the player. If it is, just randomly pick a new location again.
If you do not want to put your spawn code inside of the star script when you create the star you can set a delegate callback in the star script to call back to the script that is spawning it letting it know it needs to be moved. Or make the spawner a singleton or even implement an eventsystem to fire an event when the object is destroyed letting the manager know to move that specific object.
If you would like to just go with the example code snippet I provided and are having trouble implementing the circle cast, let me know and I can provide another snippet.
Edit: I changed the code around a bit. Now the spawner will just spawn a single star and the star handles where it moves after it collides.
I need to make somehow, that when a player runs through raycast, the score value updates by one. But instead, it updates every frame.
I tried to fix it with boolean check, but anyway, it's work as before.
Where did I make a mistake?
Here's the code:
public class ScoreBehavior : MonoBehaviour{
public delegate void ScoreUpOnPass();
public static event ScoreUpOnPass onRayHit;
private int score = 0;
private bool hitOnce = false;
void Start()
{
}
void Update()
{
RaycastHit hit;
Ray checkRay = new Ray(transform.position, Vector3.down);
if(Physics.Raycast(checkRay, out hit))
{
if (hit.collider.tag == "Player" && !hitOnce)
{
hitOnce = true;
Debug.Log(score); // updates every frame
onRayHit?.Invoke();
}
else
{
hitOnce = false;
}
}
}
}
I would try moving your if check a bit in case it hits nothing or hits an object that is not tagged player.
void Update()
{
RaycastHit hit;
Ray checkRay = new Ray(transform.position, Vector3.down);
if (Physics.Raycast(checkRay, out hit))
{
if (hit.collider.tag == "Player" && !hitOnce)
{
hitOnce = true;
Debug.Log(score); // updates every frame
onRayHit?.Invoke();
}
}
else if (hitOnce)
{
hitOnce = false;
}
}
I would recommend to use OnTriggerEnter(). Raycasting is just not a correct choice of instrument in this case.
Add a collider at the score point, set it to isTrigger = true and use OnTriggerEnter(Collider col) to check who has entered the trigger area. It will be triggered only once for each object entering the area, and will be triggered again if the object leaves the area and then goes back, so it's the best instrument for this task.
I'm trying to make a platformer game that uses 2D sprites in 3D space. For some reason, though the bullet the player shoots fires correctly from the GO that's a child of the player, it won't collide with anything (enemies, other objects, etc.) in either 2D or 3D. I have a 3D character controller on the parent player GO, but that doesn't affect the bullet object I'm firing, does it?
Colliders on everything appropriately.
Tried with IsTrigger both on and off in various combinations.
Objects are on the same layer and the same Z axis position.
//BULLET FIRING SCRIPT
void Update()
{
if (Input.GetButtonDown("Fire2") && !Input.GetButton("Fire3") &&
Time.time > nextFireTime)
{
Rigidbody2D cloneRb = Instantiate(bullet,
bulletSpawn.position, Quaternion.identity) as Rigidbody2D;
cloneRb.AddForce(bulletPrefab.transform.right *
projectileForce);
nextFireTime = Time.time + fireRate;
}
}
//____________________________________________________________
//BULLET OBJECT SCRIPT
private void Start()
{
direction = Input.GetAxisRaw("Horizontal");
if (direction == -1)
{
facingLeft = true;
}
else if (direction == 1)
{
facingLeft = false;
}
else if (direction == 0)
{
facingLeft = false;
}
if (facingLeft == false)
{
rb.velocity = transform.right * speed;
Debug.Log("Fired Bullet");
}
else
{
bulletPrefab.transform.Rotate(0, 180, 0);
firePoint.transform.Rotate(0, 180, 0);
Debug.Log("Rotated Bullet");
Debug.Log("Fired Bullet Left");
rb.velocity = transform.right * speed;
}
}
// Update is called once per frame
void Update()
{
}
public void OnTriggerEnter2D(Collider2D collider)
{
Debug.Log("Bullet Hit:");
Debug.Log(collider.name);
Enemy enemy = collider.GetComponent<Enemy>();
if (enemy != null)
{
enemy.TakeDamage(damage);
}
Destroy(gameObject);
}
Expected Result: Bullet object collides with other objects, prints Debug.Log output and gets destroyed.
Actual Result: Bullet object fires through, in front of, or behind other objects that also have colliders and there is no Debug.Log output. Bullet does not get destroyed and so instantiates clones infinitely when assigned input is entered.
Fixed issue by checking Default/Default in the Layer Collision Matrix under Edit-->Project Settings-->Physics. Not sure if it's supposed to be checked by default and somehow got unchecked but checking it solved the problem.
The way this game works is that the game starts off with a Largest Ball. When the rocket hits the large ball it splits into two medium balls and then into two small balls. When the rocket hits the smallest ball it gets destroyed.
The problem I'm having is that when the rocket collides with the ball. The rocket gets destroyed, but the ball does "not" divide into two Large balls and so forth.
I just noticed this and I'm wondering if my problem will be fixed if I turn this code statement to == "smallest ball" instead of !=.
if (target.tag == "Rocket")
{
if (gameObject.tag != "Smallest Ball")
{
InstantializeBallsonoff();
}
else {
AudioSource.PlayClipAtPoint(popsounds[Random.Range(0, popsounds.Length)], transform.position);
//play random audio in the popsounds array at current position of ball
gameObject.SetActive(false); //deactivate the gameobject
}
}
}//ontriggerenter
This is the full code for my ball Script
using UnityEngine;
using System.Collections;
public class Ball : MonoBehaviour {
private float forceX, forceY;
private Rigidbody2D ball;
[SerializeField]
private bool moveLeft, moveRight;
[SerializeField]
private GameObject originalBall;
private GameObject ball1, ball2;
private Ball ball1script, ball2script;
[SerializeField]
private AudioClip[] popsounds; //array
// Use this for initialization
void Awake () {
ball = GetComponent<Rigidbody2D>();
ballspeed();
}
// Update is called once per frame
void Update () {
ballmovement();
}
void InstantiatingBalls()
{
if (this.gameObject.tag != "Smallest Ball")
{
ball1 = Instantiate(originalBall); //create copy of originalball into ball1
ball2 = Instantiate(originalBall);
ball1.name = originalBall.name;
ball2.name = originalBall.name;
ball1script = ball1.GetComponent<Ball>(); //get the ball script
ball2script = ball2.GetComponent<Ball>();
}
}//InstantiatingBalls
void InstantializeBallsonoff() {
InstantiatingBalls();
Vector3 temp = transform.position; //start from current ball location
ball1.transform.position = temp;
ball1script.setmoveLeft(true);
ball2.transform.position = temp;
ball2script.setmoveRight(true);
ball1.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 2.5f); //x,y
ball2.GetComponent<Rigidbody2D>().velocity = new Vector2(0, 2.5f); //x,y
AudioSource.PlayClipAtPoint(popsounds[Random.Range(0, popsounds.Length)], transform.position);
//play random audio in the popsounds array at current position of ball
gameObject.SetActive(false); //deactivate the gameobject
}//InstantializeBallsonoff
public void setmoveLeft(bool moveLeft) { //canMoveLeft
this.moveLeft = moveLeft;
this.moveRight = !moveLeft; //moveRight is now false b/c we set moveLeft to true
}
public void setmoveRight(bool moveRight) {//canMoveRight
this.moveRight = moveRight;
this.moveLeft = !moveRight;
}
void ballmovement() {
if (moveLeft) {
Vector3 temp = transform.position; //current position of ball
temp.x -= Time.deltaTime; // represent time per frame
transform.position = temp;
}
if (moveRight) {
Vector3 temp = transform.position; //current position of ball
temp.x += Time.deltaTime; // represent time per frame
transform.position = temp;
}
}
void ballspeed() {
forceX = 2.5f;
switch (this.gameObject.tag) {
//this refers to gameobject that holds this script
case "Largest Ball":
forceY = 11.5f;
break;
case "Large Ball":
forceY = 10.5f;
break;
case "Medium Ball":
forceY = 9f;
break;
case "Small Ball":
forceY = 8f;
break;
case "Smallest Ball":
forceY = 7f;
break;
}//switch
}//ballspeed
void OnTriggerEnter2D (Collider2D target) {
if (target.tag == "Ground") {
ball.velocity = new Vector2(0, forceY);
}
if (target.tag == "Right Wall") {
setmoveLeft(true);
/*moveRight = false;
moveLeft = true;*/
}
if (target.tag == "Left Wall")
{
setmoveRight(true);
/*moveRight = true;
moveLeft = false;*/
}
if (target.tag == "Rocket")
{
if (gameObject.tag != "Smallest Ball")
{
InstantializeBallsonoff();
}
else {
AudioSource.PlayClipAtPoint(popsounds[Random.Range(0, popsounds.Length)], transform.position);
//play random audio in the popsounds array at current position of ball
gameObject.SetActive(false); //deactivate the gameobject
}
}
}//ontriggerenter
}//ball
This is partial of my code where the rocket gets destroyed when it collides with the large ball & the top. This is the other part that I am having trouble with.
void OnTriggerEnter2D(Collider2D target) {
if (target.tag == "Top") {
Destroy(gameObject);
}
string[] ballhit = target.name.Split();
/*array ballhit
split = deletes the space between two words and make it so it takes 2 spaces in the array*/
for (int s = 0; s < ballhit.Length; s++) {
Debug.Log("The array contains: " +ballhit [s]);
if (ballhit.Length > 1)
{ //ball names will always be more than 1 length "Largest Ball"
if (ballhit[1] == "Ball")
{
Destroy(gameObject);
}//destroy object
}//ballhit name length
}// name increments
}//triggerCollider
This is my full Rocket Script
using UnityEngine;
using System.Collections;
public class Rocket : MonoBehaviour {
private Rigidbody2D rocket;
private float speed = 5f;
// Use this for initialization
void Awake () {
rocket = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update () {
rocket.velocity = new Vector2(0, speed); //x, y rocket movement
}
void OnTriggerEnter2D(Collider2D target) {
if (target.tag == "Top") {
Destroy(gameObject);
}
string[] ballhit = target.name.Split();
/*array ballhit
split = deletes the space between two words and make it so it takes 2 spaces in the array*/
for (int s = 0; s < ballhit.Length; s++) {
Debug.Log("The array contains: " +ballhit [s]);
if (ballhit.Length > 1)
{ //ball names will always be more than 1 length "Largest Ball"
if (ballhit[1] == "Ball")
{
Destroy(gameObject);
}//destroy object
}//ballhit name length
}// name increments
}//triggerCollider
}//rocket
Your code is much more complicated than it needs to be an therefore the actual error is difficult to find.
First off, your moveLeft and moveRight bools are mutually exclusive. You need only one of them. I would event prefer to replace both with a public int currentDirection which you set to 1 for right and -1 for left.
Your new ballMovement method could then simply be:
void MoveBall() // C# methods are upper-case by convention
{
transform.position += Vector3.right * currentDirection * Time.deltaTime;
}
The way you check with which type of ball you are colliding is not very safe. I would suggest you use an enum to differentiate the ball sizes.
public enum BallSizes { Largest, Large, Medium, Small, Smallest }; // The different possible values
public BallSize size = BallSizes.Largest; // The balls current size, the biggest size by default
This also allows you to store your y-axis force values in a matching array and access them easily without the use of a switch or else-if:
private float[] forcesY = new float[]{ 11.5f, 10.5f, 9f, 8f, 7f };
void SetBallSpeed()
{
forceX = 2.5f;
forceY = forcesY[(int)size];
}
I think the problem you had with the ball not splitting is is connected to this.
Upon collision, you detected the type of ball you collided with, by examining its tag. But you always Instantiate the new balls using the same prefab, and I never saw you change the tag. So what type of ball are you creating?
If you use the method I described above, you can simply assign a general tag "Ball" and handle the rest with the BallSizes-enum. When creating the new balls you can do the following:
[SerializedField] // The SerializedField property makes it show up in the inspector, even though it is private
private Ball ballPrefab; // Attention: Type "Ball"
public void IsHit() // Method to execute upon rocket collision
{
if(ball.size != BallSizes.Smallest)
{
Ball leftBall = Instantiate(ballPrefab). // Notice that, when you assign you prefab as Type "Ball", you directly get the Ball-Component as the return value.
leftball.direction = -1;
leftball.size = (BallSizes)(size + 1); // Add one to size, to get get the next enum value, which is the next smaller size.
Ball rightBall = .... // Do same stuff for the right ball
}
Destroy(this.gameObject);
}
I don't know how you plan to visualise the type of ball, but you might want to add a float[] ballScales, which you use to shrink the ball's actual size, something like: leftBall.transform.localScale = Vector3.one * ballScales[(int)size].
Finally, another reason your collision does not work might well be, that you handle it in two different places. If you destroy the rocket after it detects collision with the ball, nothing has happend to the ball yet. If the ball is checking for collision afterward it will most likely not find the rocket, because you already destroyed it. A clean way to solve this, would be to let the rocket notify the ball of the collision:
void OnTriggerEnter2D(Collider2D target)
{
if(target.tag == "Top")
Destroy(gameObject);
else if(target.tag == "Ball")
{
target.GetComponent<Ball>().IsHit(); // We know this component should exist when the object is tagged "Ball"
Destroy(gameobject);
}
}
You can then remove that from you ball collision and shorten it to this:
void OnTriggerEnter2D (Collider2D target)
{
if(target.tag == "Ground")
ball.velocity = new Vector2(0, forceY);
if(target.tag == "Right Wall" || target.tag == "Left Wall")
direction *= -1; // Inverts the direction, + <-> -
}
Phew, that was a lot.
I hope this is still relevant and answers more questions than it raises.
Happy coding!
I have a death animation already. I want a particle system particleRed to start along with the death animation. I have a private variable particleRed and I have initiated it in the awake function.
What should I do now?
using UnityEngine;
using System.Collections;
using UnityStandardAssets.CrossPlatformInput;
public class CharacterController2D : MonoBehaviour {
// player controls
[Range(0.0f, 10.0f)] // create a slider in the editor and set limits on moveSpeed
public float moveSpeed = 3f;
public float jumpForce = 600f;
// player health
public int playerHealth = 1;
// LayerMask to determine what is considered ground for the player
public LayerMask whatIsGround;
// Transform just below feet for checking if player is grounded
public Transform groundCheck;
// player can move?
// we want this public so other scripts can access it but we don't want to show in editor as it might confuse designer
[HideInInspector]
public bool playerCanMove = true;
// SFXs
public AudioClip coinSFX;
public AudioClip deathSFX;
public AudioClip fallSFX;
public AudioClip jumpSFX;
public AudioClip victorySFX;
// private variables below
// store references to components on the gameObject
Transform _transform;
Rigidbody2D _rigidbody;
Animator _animator;
AudioSource _audio;
ParticleSystem particleRed;
// hold player motion in this timestep
float _vx;
float _vy;
// player tracking
bool facingRight = true;
bool isGrounded = false;
bool isRunning = false;
bool _canDoubleJump = false;
// store the layer the player is on (setup in Awake)
int _playerLayer;
// number of layer that Platforms are on (setup in Awake)
int _platformLayer;
void Awake () {
// get a reference to the components we are going to be changing and store a reference for efficiency purposes
_transform = GetComponent<Transform> ();
_rigidbody = GetComponent<Rigidbody2D> ();
if (_rigidbody==null) // if Rigidbody is missing
Debug.LogError("Rigidbody2D component missing from this gameobject");
_animator = GetComponent<Animator>();
if (_animator==null) // if Animator is missing
Debug.LogError("Animator component missing from this gameobject");
_audio = GetComponent<AudioSource> ();
if (_audio==null) { // if AudioSource is missing
Debug.LogWarning("AudioSource component missing from this gameobject. Adding one.");
// let's just add the AudioSource component dynamically
_audio = gameObject.AddComponent<AudioSource>();
}
particleRed = GetComponent<ParticleSystem>();
// determine the player's specified layer
_playerLayer = this.gameObject.layer;
// determine the platform's specified layer
_platformLayer = LayerMask.NameToLayer("Platform");
}
// this is where most of the player controller magic happens each game event loop
void Update()
{
// exit update if player cannot move or game is paused
if (!playerCanMove || (Time.timeScale == 0f))
return;
// determine horizontal velocity change based on the horizontal input
_vx = CrossPlatformInputManager.GetAxisRaw ("Horizontal");
// Determine if running based on the horizontal movement
if (_vx != 0)
{
isRunning = true;
} else {
isRunning = false;
}
// set the running animation state
_animator.SetBool("Running", isRunning);
// get the current vertical velocity from the rigidbody component
_vy = _rigidbody.velocity.y;
// Check to see if character is grounded by raycasting from the middle of the player
// down to the groundCheck position and see if collected with gameobjects on the
// whatIsGround layer
isGrounded = Physics2D.Linecast(_transform.position, groundCheck.position, whatIsGround);
// Allow Double Jump after grounded
if (isGrounded)
{
_canDoubleJump = true;
}
// Set the grounded animation states
_animator.SetBool("Grounded", isGrounded);
if (isGrounded && CrossPlatformInputManager.GetButtonDown ("Jump")) { // If grounded AND jump button pressed, then allow the player to jump
DoJump ();
} else if (_canDoubleJump && CrossPlatformInputManager.GetButtonDown ("Jump"))
{
DoJump();
// double jumo can be possible once
_canDoubleJump = false;
}
// If the player stops jumping mid jump and player is not yet falling
// then set the vertical velocity to 0 (he will start to fall from gravity)
if(CrossPlatformInputManager.GetButtonUp("Jump") && _vy>0f)
{
_vy = 0f;
}
// Change the actual velocity on the rigidbody
_rigidbody.velocity = new Vector2(_vx * moveSpeed, _vy);
// if moving up then don't collide with platform layer
// this allows the player to jump up through things on the platform layer
// NOTE: requires the platforms to be on a layer named "Platform"
Physics2D.IgnoreLayerCollision(_playerLayer, _platformLayer, (_vy > 0.0f));
}
// Checking to see if the sprite should be flipped
// this is done in LateUpdate since the Animator may override the localScale
// this code will flip the player even if the animator is controlling scale
void LateUpdate()
{
// get the current scale
Vector3 localScale = _transform.localScale;
if (_vx > 0) // moving right so face right
{
facingRight = true;
} else if (_vx < 0) { // moving left so face left
facingRight = false;
}
// check to see if scale x is right for the player
// if not, multiple by -1 which is an easy way to flip a sprite
if (((facingRight) && (localScale.x<0)) || ((!facingRight) && (localScale.x>0))) {
localScale.x *= -1;
}
// update the scale
_transform.localScale = localScale;
}
// if the player collides with a MovingPlatform, then make it a child of that platform
// so it will go for a ride on the MovingPlatform
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag=="MovingPlatform")
{
this.transform.parent = other.transform;
}
}
// if the player exits a collision with a moving platform, then unchild it
void OnCollisionExit2D(Collision2D other)
{
if (other.gameObject.tag=="MovingPlatform")
{
this.transform.parent = null;
}
}
//make the player jump
void DoJump()
{
// reset current vertical motion to 0 prior to jump
_vy = 0f;
// add a force in the up direction
_rigidbody.AddForce (new Vector2 (0, jumpForce));
// play the jump sound
PlaySound(jumpSFX);
}
// do what needs to be done to freeze the player
void FreezeMotion() {
playerCanMove = false;
_rigidbody.isKinematic = true;
}
// do what needs to be done to unfreeze the player
void UnFreezeMotion() {
playerCanMove = true;
_rigidbody.isKinematic = false;
}
// play sound through the audiosource on the gameobject
void PlaySound(AudioClip clip)
{
_audio.PlayOneShot(clip);
}
// public function to apply damage to the player
public void ApplyDamage (int damage) {
if (playerCanMove) {
playerHealth -= damage;
if (playerHealth <= 0) { // player is now dead, so start dying
PlaySound(deathSFX);
StartCoroutine (KillPlayer ());
}
}
}
// public function to kill the player when they have a fall death
public void FallDeath () {
if (playerCanMove) {
playerHealth = 0;
PlaySound(fallSFX);
StartCoroutine (KillPlayer ());
}
}
// coroutine to kill the player
IEnumerator KillPlayer()
{
if (playerCanMove)
{
// freeze the player
FreezeMotion();
// play the death animation
_animator.SetTrigger("Death");
// After waiting tell the GameManager to reset the game
yield return new WaitForSeconds(2.0f);
if (GameManager.gm) // if the gameManager is available, tell it to reset the game
GameManager.gm.ResetGame();
else // otherwise, just reload the current level
Application.LoadLevel(Application.loadedLevelName);
}
}
public void CollectCoin(int amount) {
PlaySound(coinSFX);
if (GameManager.gm) // add the points through the game manager, if it is available
GameManager.gm.AddPoints(amount);
}
// public function on victory over the level
public void Victory() {
PlaySound(victorySFX);
FreezeMotion ();
_animator.SetTrigger("Victory");
if (GameManager.gm) // do the game manager level compete stuff, if it is available
GameManager.gm.LevelCompete();
}
// public function to respawn the player at the appropriate location
public void Respawn(Vector3 spawnloc) {
UnFreezeMotion();
playerHealth = 1;
_transform.parent = null;
_transform.position = spawnloc;
_animator.SetTrigger("Respawn");
}
public void EnemyBounce ()
{
DoJump ();
}
}
I suggest making a empty game object prefab that holds the particle system. Then when you want to use the particle system, just instantiate the object. That is the easiest way i've found to go about it, and its rather versatile. Another way is, you could make the empty game object a child of your player, and then activate it when you want to use it. The second way isn't as ideal, but will get the job done too.
For the ParticleSystem component that you have added to the gameObject, set the enabled property to false by unchecking the enabled checkbox on the component.
Then in the KillPlayer function
particleRed.enabled = true;
Additionally you can ensure it is disabled in the Awake function by setting it to false.