I m coding a 2d platform game. In the game, there are allies and enemies walks toward each other. If they collide each other, their own timer script starts countdown and the health reducing by the time as periods. If a characters health equals to zero, i destroy that gameobject. I add some booleans each character to detect they are colliding each other or not. While colliding both gameobjects, if one destroys, other colliding gameobject still continius colliding, although there is no colliding object. This happens just other colliding object is destroyed.
public float setSpeed;
public bool enemyColliding;
float speed;
void Start () {
}
// Update is called once per frame
void Update () {
speed= setSpeed;
GetComponent<Rigidbody2D> ().velocity = new Vector2 (speed,GetComponent<Rigidbody2D>().velocity.y);
if (enemyColliding) {
attackAnimation ();
}
else
{
walkAnimation();
}
}
void OnTriggerEnter2D(Collider2D coll)
{
if (coll.gameObject.tag == "dusman" /*enemy*/ ) {
enemyColliding= true;
}
}
void OnTriggerExit2D(Collider2D coll)
{
if (coll.gameObject.tag=="dusman" /*enemy*/) {
enemyColliding= false;
}
}
void attackAnimation()
{
Animator animator = this.gameObject.GetComponent<Animator> ();
animator.runtimeAnimatorController = Resources.Load ("AllyWr2AttackAnim") as RuntimeAnimatorController;
}
void walkAnimation ()
{
Animator animator = this.gameObject.GetComponent<Animator> ();
animator.runtimeAnimatorController = Resources.Load ("AllyWr2WalkAnim") as RuntimeAnimatorController;
}
Any help please...
void OnTriggerExit2D(Collider2D coll)
{
enemyColliding= false;
}
try this
Related
My problem is that I'm making a game with unity, and what I want to do is when the enemy in my game hits the obstacle, it does x damage every one second.
There's a collider and health script on the "desk" obstacle, and a collider and script for movement and attacking on the enemy.
The enemy stops when colliding with the desk object, and does damage! but, the damage is continuous... I've tried coroutines and Invoke's but all the results are the same; 10 damage per trigger detection, not per second.
Here are the scripts:
Enemy movement and attack:
private Animator anim;
public GameObject Desk;
private DeskHealth deskHealth;
//private bool inQueue = false;
private bool collidingWithDesk;
public float timeAfterStart;
[Range(0,10)]
public float attackSpeedEnemy = 1f;
[Range(10,100)]
public float walkSpeed;
[SerializeField] float damageDealtToDesk = 10f;
void Start () {
anim = GetComponent<Animator>();
deskHealth = GetComponent<DeskHealth>();
collidingWithDesk = false;
}
void Update()
{
if (collidingWithDesk == false)
{
enemyIsWalking();
}
}
void enemyIsWalking()
{
transform.Translate(0, 0, (-walkSpeed * Time.deltaTime));
}
IEnumerator enemyIsAttacking()
{
var deskHealth = Desk.GetComponent<DeskHealth>();
deskHealth.DealDamageToDesk(damageDealtToDesk);
yield return new WaitForSeconds(5f);
}
void OnTriggerStay(Collider otherCollider)
{
if (otherCollider.tag == "Desk")
{
collidingWithDesk = true;
transform.Translate(0, 0, 0);
anim.Play("enemyHit");
StartCoroutine(enemyIsAttacking());
}
}
desk Health:
[SerializeField] float deskHealth;
Animator anim;
public void DealDamageToDesk(float deskDamage)
{
deskHealth -= deskDamage;
if (deskHealth <= 0)
{
print("am ded");
//anim.Play("deskDestroyed");
}
}
For what the doc says "OnTriggerStay is called once per physics update for every Collider other that is touching the trigger." Which mean that your code :
if (otherCollider.tag == "Desk")
{
collidingWithDesk = true;
transform.Translate(0, 0, 0);
anim.Play("enemyHit");
StartCoroutine(enemyIsAttacking());
}
will be called every update then pause for 5 seconds because of yield return new WaitForSeconds(5f); You should use OnColliderEnter or it might be even better to use OnTriggerEnter instead, because this one will be called once. Then change the value inside the WaitForSeconds call to 1 if you want it once per second.
Also as specified by Draco18s your yield wait for nothing.
You should do something like that :
IEnumerator enemyIsAttacking()
{
var deskHealth = Desk.GetComponent<DeskHealth>();
while(collidingWithDesk)
{
deskHealth.DealDamageToDesk(damageDealtToDesk);
yield return new WaitForSeconds(1f);
}
}
void OnTriggerExit(Collider otherCollider)
{
if (otherCollider.tag == "Desk")
{
collidingWithDesk = false;
// rest of your code
}
}
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.
Title says it all.
I provided an NPC with the following script, which should make him look and bark at the player.
When the player comes into the NPC's reach, however, the NPC starts walking towards the player instead of just facing him.
Any thoughts?
using UnityEngine;
public class Barking : MonoBehaviour {
public AudioSource barkingAudio;
private GameObject player;
private bool barking;
void Start () {
player = GameObject.FindGameObjectWithTag("Player");
barking = false;
}
void Update () {
if (barking)
lookAtPlayer();
}
private void lookAtPlayer()
{
transform.LookAt(player.transform.position, Vector3.up);
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject == player)
{
barking = true;
barkingAudio.mute = false;
barkingAudio.Play();
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject == player) {
barking = false;
barkingAudio.mute = true;
barkingAudio.Stop();
}
}
}
Since I was using a Rigidbody and rotating the transform manually, there was some unexpected behaviour.
I found some code online which I could replace the Transform.LookAt method with:
var qTo = Quaternion.LookRotation(player.transform.position - transform.position);
qTo = Quaternion.Slerp(transform.rotation, qTo, 10 * Time.deltaTime);
GetComponent<Rigidbody>().MoveRotation(qTo);
This fixed my problem!
I have a very annoying bug, and I can't get rid of it.
The situation is, that I have a parent with the following script attached, and a trigger box2d collider. It has a child, with a rigidbody2d(kinematic, gravity=0, freeze position x, and rotation z), a sprite renderer and a polygon collider (with 4 edges).
My problem is, when the scene is loaded, sometimes my child objects (always random how much of them and which ones), jumps to transform.position 0,0,0.
I link the script, that is attached to the parent
using UnityEngine;
using System.Collections;
public class FallingSpikeHazard : MonoBehaviour
{
public GameObject spike;
private Rigidbody2D spikeRigidbody;
[SerializeField]
private Vector3 startPosition;
void Awake ()
{
startPosition = spike.transform.localPosition;
}
void Start ()
{
spikeRigidbody = spike.GetComponent<Rigidbody2D> ();
Helper.JustReset += ResetMe;
Invoke ("CheckPosition", Time.deltaTime);
}
void CheckPosition ()
{
if (spike.transform.localPosition != startPosition) {
Debug.LogError ("t1" + spike.transform.localPosition);
spike.transform.localPosition = startPosition;
Debug.LogError ("t2" + spike.transform.localPosition);
}
}
void OnDestroy ()
{
Helper.JustReset -= ResetMe;
}
void ResetMe ()
{
spikeRigidbody.gravityScale = 0;
spikeRigidbody.isKinematic = true;
if (startPosition != Vector3.zero) {
spike.transform.localPosition = startPosition;
}
}
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag.Equals ("Player")) {
spikeRigidbody.isKinematic = false;
spikeRigidbody.gravityScale = 1;
}
}
}
Events are not called, in other hand, if I disable the script, it keeps happening. Nothing have reference to these GameObjects. I don't have animations, or animator attached.
What could cause my problem?
You need to have a Rigidbody2D component in the parent GameObject in order for the OnTriggerEnter function to be called.