As I am new to Unity3D and started with Space Shooter tutorial. Now I am unable to create a simple life system for the space ship, probably, it's a silly mistake but I've been on it for few hours already, searching for the solution.
The OnTriggerEnter code is:
void OnTriggerEnter (Collider other)
{
if (other.CompareTag ("Boundary") || other.CompareTag ("Enemy"))
{
return;
}
if (explosion != null) //hit object explosion
{
Instantiate (explosion, transform.position, transform.rotation);
}
if (other.tag == "Player" && playerHealth >= 1) {
playerHealth--;
gameController.SubLive (playerHealth);
}
if (other.tag == "Player" && playerHealth <= 0) {
Instantiate (playerExplosion, other.transform.position, other.transform.rotation);
Destroy (other.gameObject);
gameController.GameOver ();
}
Destroy (gameObject); //destroy hit object
gameController.AddScore (scoreValue);
/**/
}
I've found that the solution is to decrement player health every time collision happens, however, it does only work the first time once player ship collides with asteroid or enemy ship. The triggers are player ship, enemy ship and bolts (shot from ships). All of the objects has rigidbody. Could you please suggest what am I doing wrong?
Thanks in advance!
You can find non-edited Space Shooter script Here
Ugh! After getting some rest and coming back with a fresh mind I managed to solve it myself! (Was easier that i thought, though!)
void OnTriggerEnter (Collider other)
{
if (other.CompareTag ("Boundary") || other.CompareTag ("Enemy"))
{
return;
}
if (explosion != null)
{
Instantiate (explosion, transform.position, transform.rotation);
}
if (other.tag == "Bolt")
{
Destroy (other.gameObject);
}
if (other.tag == "Player")
{
gameController.SubLive (); //if player ship collides asteroid or enemy ship reduces 1 health
if (gameController.isDead == true) //explodes ship once playerHealth is 0
{
Instantiate (playerExplosion, other.transform.position, other.transform.rotation);
gameController.GameOver ();
Destroy (other.gameObject);
}
}
gameController.AddScore (scoreValue);
Destroy (gameObject);
}
Script piece in gameController:
<...>
private int playerHealth;
public bool isDead;
<...>
void Start ()
{
playerHealth = 3;
isDead = false;
}
<...>
public void SubLive()
{
playerHealth--;
UpdateLives ();
if (playerHealth <= 0)
{
isDead = true;
}
}
void UpdateLives ()
{
livesText.text = "Lives: " + playerHealth;
}
Related
I am Working on an multiplayer fps game the code throws an missing reference exception in the line given below the error doesn't show up when there is only one player in the room but it starts coming as soon as another player joins the room
private IEnumerator Shoot()
{
ammoLeft -= 1;
animator.SetBool("fire", true);
RaycastHit hit;
if (Physics.Raycast(playerCam.position, playerCam.forward, out hit, range))
{
//Missing Reference Expection The transform you are accessing is destroyed
//code works in singleplayer
if (hit.transform.tag == "Player" && hit.transform != null)
{
HealthManager HealthScript = hit.transform.gameObject.GetComponent<HealthManager>();
if (HealthScript != null)
{
HealthScript.TakeDamage(damage);
}
}
}
yield return new WaitForSeconds(0.3f);
animator.SetBool("fire", false);
if (ammoLeft <= 0f)
{
StartCoroutine("Reload");
}
Error in this line
Physics.Raycast(playerCam.position, playerCam.forward, out hit, range)
I have checked if my camera is null but the problem doesn't fix so I am clueless
private void Awake()
{
if (!pv.IsMine)
{
Destroy(ui);
}
if (playerCam == null)
{
playerCam = FindObjectOfType<Camera>().transform;
}
ammoLeft = magazineSize;
animator = GetComponent<Animator>();
}
Inspector Window
https://i.stack.imgur.com/Tc69B.png
This is the code that I have on my player script:
void OnTriggerEnter2D (Collider2D collider2D)
{
if (collider2D.gameObject.tag == "powerup")
{
PoweredUp = true;
PowerupTimer = PowerupTimer;
PowerupTimer -= Time.deltaTime;
}
}
...and this is on the powerup itself:
void OnTriggerEnter2D(Collider2D collider2D)
{
if (collider2D.gameObject.tag == "Player")
{
Destroy(gameObject);
}
}
For some reason, any prefabs that I drop directly into my scene work perfectly, however instantiated ones get destroyed, but for some reason, do not trigger the "PoweredUp" boolean.
Here is a more complicated script that I have on the spawner objects:
public GameObject powerup;
public float minWait;
public float maxWait;
private bool isSpawning;
IEnumerator SpawnObject(float seconds)
{
Debug.Log("Waiting for " + seconds + " seconds");
yield return new WaitForSeconds(seconds);
Instantiate(powerup, transform.position, transform.rotation);
isSpawning = false;
}
void Update()
{
if (!isSpawning)
{
isSpawning = true;
StartCoroutine(SpawnObject(UnityEngine.Random.Range(minWait, maxWait)));
}
Any solutions, or ways I could have done this more efficiently?
UPDATE: I found out that the script on the Player object is running fine, but the boolean still isn't changing.
Ok I got it, there was a compiler warning referencing the line "PowerupTimer = PowerupTimer" so I just changed it to "PowerupTimer = 7f" which is pretty much the same thing.
The problem is that I what to create an openable door. This door should open when the player enter the Box Collider which is connected to the door. But the problem is when the door begins to open and to rotate, Collider starts to rotate too which brings me a lot of problems with usind such an idea. I try to create EmptyObject with its Collider but I can't connect this Collider with script and OnTriggerEnter function itself. Maybe I don't understand something, who knows, I'm just a begginer. How knows how to help, please write an answer.
My code if somebody needs it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class openDoor : MonoBehaviour {
public Vector3 Rotation_;
private int i;
public float speed;
bool opentheDoor;
bool closetheDoor;
// Use this for initialization
void Start () {
opentheDoor = false;
closetheDoor = false;
}
// Update is called once per frame
void Update () {
if (opentheDoor == true) {
this.transform.Rotate (Rotation_ * Time.deltaTime * speed);
i += 1;
if (i == 70) {
opentheDoor = false;
i = 0;
}
}
if (closetheDoor == true) {
this.transform.Rotate (-Rotation_ * Time.deltaTime * speed);
i += 1;
if (i == 70) {
closetheDoor = false;
i = 0;
}
}
}
void OnTriggerEnter (Collider other) {
if (other.gameObject.tag == "Player") { {
opentheDoor = true;
}
}
}
void OnTriggerExit (Collider other) {
if (other.gameObject.tag == "Player") {
closetheDoor = true;
}
}
}
This is how i would handle the scenerio
Take
DoorHandler.cs
public class DoorHandler : MonoBehaviour {
public Door door;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
door.OpenDoor();
}
}
}
This should be attached to Parent of the door.
Next Take
Door.cs
public class Door : MonoBehaviour {
public bool isOpened = false;
public void OpenDoor()
{
if (!isOpened)
{
isOpened = true;
Debug.Log("OPEN");
//OPEN DOOR CODE!
}
}
}
Attach this to the Door GameObject
NOTE
The hierarchy would be like DoorHandler->Door->DoorModel (where Door is just an empty gameobject pivot of the Door)
In DoorHandler GameObject attach BoxCollider and Check Mark IsTrigger.
Also Player SHOULD HAVE A RIGIDBODY (preferably Kinametic) and obviously a collider
So When Player enters the DoorHandler's Collider -> The DoorHandler's OnTriggerEnter will be triggered and finally Call the Door to OpenDoor()
Add another check in OnTriggerEnter that checks if the door is currently opening or not.
void OnTriggerEnter (Collider other) {
if (other.gameObject.tag == "Player" && !opentheDoor) {
opentheDoor = true;
}
}
attach the door to an empty object. put the trigger on the empty object. then make the ontrigger entry rotate the door, not the paent object, and the collider will remain in place.
Parent
-child(door)
-child(collider)
I'm trying to create objects that mark the cell that I can visit. I mark them with red square:
My code for creating objects:
using UnityEngine;
using System.Collections;
using System;
public class SpawnCheck : MonoBehaviour {
public GameObject checkObject;
public bool canSpawnCheck = true;
Vector2 boxSize;
public GameObject spawnedObject;
// Use this for initialization
void Start () {
Debug.Log("Into spawn check");
}
void OnTriggerEnter2D(Collider2D other) {
Debug.Log("Enter trigger collision");
canSpawnCheck = false;
if (other.gameObject.tag == "Target") {
Debug.Log ("Found Target");
}
if (other.gameObject.tag == "Wall") {
canSpawnCheck = false;
}
if (other.gameObject.tag == "Check") {
canSpawnCheck = false;
}
}
void OnTriggerExit2D(Collider2D other) {
Debug.Log("Exit trigger collision");
canSpawnCheck = true;
}
// Update is called once per frame
void Update () {
Debug.Log ("canSpawnCheck " + canSpawnCheck);
if (canSpawnCheck == true) {
Vector3 currentPosition = this.gameObject.transform.position;
Vector3 spawnPos = new Vector3 (Mathf.Round (currentPosition.x), Mathf.Round (currentPosition.y),0);
Debug.Log ("Physics.CheckSphere " + Physics.CheckSphere (spawnPos, 5));
if (!Physics.CheckSphere(spawnPos,5)) {
spawnedObject = (GameObject)Instantiate (checkObject, spawnPos, Quaternion.identity);
this.gameObject.GetComponentInParent<AILerp> ().possibleTargets.Add (spawnedObject);
}
}
}
}
My problem: as Physics.CheckSphere(spawnPos,5) always return false my code spawns too many red squares and spawn them upon each other. I want red squares to be created only once and never created on walls (white squares).
Your Check(Clone) GameObject has Box Collider 2D attached to it. Therefore every physics function you must use should be Physics2D.something not Physics.something. Notice the keyword there "2D".
If you use just Box Collider without the 2D in it, then you can use Physics.something. So, Physics.CheckSphere cannot be used with a 2D collider.
Check(Clone) is a SpriteRenderer, 2D Collider is appropriate. You just need to use one of the Physics2D overlap functions such Physics2D.OverlapBox, Physics2D.OverlapArea or Physics2D.OverlapCircle. Which ever one you prefer.
Okay, I am making a simple game mechanic where you are a ball rolling along a small panel. On the edge of the panel are 8 child objects. 4 of them are triggers on the edges of the panel, and 4 of them are empty game objects 1 unit away from each edge of the panel for the location of the next panel prefab to spawn at. The ball has a trigger on it that detects the location of the empty game objects to tell the panel prefab where to spawn. When the ball enters a specific trigger frm the panel the ball is suppose to instantiate a panel prefab on the location that I assign based on the trigger the ball enters. Here is my code:
public GameObject panelPrefab;
Transform frontSpawn;
Transform backSpawn;
Transform leftSpawn;
Transform rightSpawn;
private bool allowSpawn;
void Awake()
{
allowSpawn = true;
}
void OnTriggerStay(Collider spawn)
{
if (spawn.gameObject.tag == "FrontSpawn")
{
frontSpawn = spawn.transform;
}
else if (spawn.gameObject.tag == "BackSpawn")
{
backSpawn = spawn.transform;
}
else if (spawn.gameObject.tag == "LeftSpawn")
{
leftSpawn = spawn.transform;
}
else if (spawn.gameObject.tag == "RightSpawn")
{
rightSpawn = spawn.transform;
}
}
void OnTriggerEnter (Collider other)
{
if (other.gameObject.tag == "Front" && allowSpawn == true)
{
Instantiate (panelPrefab, frontSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
else if (other.gameObject.tag == "Back" && allowSpawn == true)
{
Instantiate (panelPrefab, backSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
else if (other.gameObject.tag == "Left" && allowSpawn == true)
{
Instantiate (panelPrefab, leftSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
else if (other.gameObject.tag == "Right" && allowSpawn == true)
{
Instantiate (panelPrefab, rightSpawn.transform.position, Quaternion.identity);
allowSpawn = false;
}
}
void OnTriggerExit (Collider other)
{
allowSpawn = true;
}
My issue is on each of the Instantiate calls, I am getting a NullReferenceException. I have the panelPrefab assigned in the unity editor, and I don't know what could be causing this! If anyone can help me here it would be GREATLY appreciated... So thank you in advance!
OnTriggerEnter is called before OnTriggerStay. The error is not due to the panelPrefab object. It might happen that your rightSpawn, leftSpawn etc. objects are null and hence cannot access the transform property of a null object.
Before instantiating verify if rightSpawn etc. is null or not and then access it's position.