OnCollisionExit() Not Working on my script unity? - c#

I Am Working With Unity 3d and know little scripting and unity well. I Came To a point where I don't know what to do. My OnCollisionExit Don't Work on collision exit there is moment = true this dont work. Somebody told me you have not reset the variable. So I Don't Know How To Make It So Please Help. Thanks In Advance
This is The Player Script This Is My Script or code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Player : MonoBehaviour
{
public Animator anim;
public Transform housepos;
public Transform deadpos;
public static bool safe1_click = false;
public bool safe1_clicked = false;
public float speed = 25;
public Rigidbody rb;
Collider mycollider;
float Walk = 8;
float jump = 7;
float sadWalk = 6;
float idle = 0;
public static bool stopwalking = false;
public static bool Jump = false;
public static bool sadwalk = false;
public static bool freeze = false;
public static bool yourchance = false;
public static bool movement = true;
public bool movement23 = true;
// Start is called before the first frame update
void Start()
{
mycollider = transform.GetComponent<Collider>();
rb = GetComponent<Rigidbody>();
anim.SetFloat("Animation", Walk);
stopwalking = false;
Jump = false;
freeze = false;
}
// Update is called once per frame
void Update()
{
movement23 = movement;
if (movement == true)
{
safe1_click = safe1_clicked;
rb.velocity = new Vector3(speed * Time.deltaTime, rb.velocity.y, 0);
}
else
{
rb.velocity = new Vector3(0,0,0);
}
if (Jump == true)
{
anim.SetFloat("Animation", jump);
}
if (Jump == true)
{
anim.SetFloat("Animation", sadWalk);
}
if (stopwalking == true)
{
anim.SetFloat("Animation", idle);
}
}
public void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "stop")
{
Debug.Log("Stopped");
spawner.stopspawn = true;
movement = false;
return;
}
if (collision.gameObject.tag == "dec")
{
Debug.Log("oh");
freeze = true;
}
}
public void OnCollisionExit(Collision collision)
{
if (collision.gameObject.tag == "stop")
{
Debug.Log("Spawning");
spawner.stopspawn = false;
movement = true;
}
if (collision.gameObject.tag == "dec")
{
Debug.Log("oh");
freeze = false;
}
}
public void OnTriggerEnter(Collider other)
{
if(other.gameObject.tag == "fre")
{
spawner.yourchance = true;
}
if (other.gameObject.tag == "Player")
{
Destroy(other.gameObject);
}
if (other.gameObject.tag == "dec")
{
freeze = true;
Debug.Log("oh");
}
if (other.gameObject.tag == "new")
{
yourchance = true;
Debug.Log("stopstop");
}
if (other.gameObject.tag == "con")
{
Debug.Log("collide happened");
movement = true;
}
}
private void OnTriggerExit(Collider other)
{
if(other.gameObject.tag == "dec")
{
freeze = false;
Debug.Log("oh");
}
}
}

Related

Optimize the game in unity

Optimization script doesn`t work. I made a script to optimize my game in unity, when the player is standing, everything is fine, But once it starts to go... Framerate Per Second starts to decrease to zero, tell me what should I do? After all, the player does not perform heavy operations, how can this load something? (I tried OnBecameVisible and OnBecameInvisible they don't work)
~Scripts~
using UnityEngine;
[RequireComponent(typeof(ObjectParameters))]
public class ObjectManager : MonoCache
{
public SpriteRenderer[] spriteRenderers;
[Space]
public ObjectParameters objectParameters;
[Space]
[SerializeField] bool freezeRotation;
bool isBuilded;
[Space]
public bool usingDragging = true;
[Space]
[SerializeField] bool usingRigidBody;
Rigidbody2D rb2D;
float gS;
[Space]
[SerializeField] bool usingSheetDrop;
SheetDrop sheetDrop;
void Start()
{
rb2D = GetComponent<Rigidbody2D>();
objectParameters = GetComponent<ObjectParameters>();
sheetDrop = GetComponent<SheetDrop>();
if (usingRigidBody == true)
{
rb2D.constraints = RigidbodyConstraints2D.FreezeAll;
gS = rb2D.gravityScale;
}
if (usingSheetDrop == true)
{
sheetDrop.enabled = false;
}
objectParameters.enabled = false;
for (int i = 0; i < spriteRenderers.Length; i++)
{
spriteRenderers[i].enabled = false;
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "PlayerDrawing")
{
if (usingRigidBody == true)
{
if (rb2D == null)
{
rb2D = GetComponent<Rigidbody2D>();
}
if (freezeRotation == false)
{
rb2D.constraints = RigidbodyConstraints2D.None;
}
}
if (usingSheetDrop == true)
{
sheetDrop.enabled = true;
}
objectParameters.enabled = true;
for (int i = 0; i < spriteRenderers.Length; i++)
{
spriteRenderers[i].enabled = true;
}
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.tag == "PlayerDrawing")
{
if (usingRigidBody == true)
{
if (rb2D == null)
{
rb2D = GetComponent<Rigidbody2D>();
}
if (rb2D.constraints != RigidbodyConstraints2D.FreezeAll || rb2D.bodyType != RigidbodyType2D.Kinematic)
{
rb2D.constraints = RigidbodyConstraints2D.FreezeAll;
}
}
}
if (usingSheetDrop == true)
{
sheetDrop.enabled = false;
}
objectParameters.enabled = false;
for (int i = 0; i < spriteRenderers.Length; i++)
{
spriteRenderers[i].enabled = false;
}
}
}
and ObjectParameters
using UnityEngine;
public class ObjectParameters : MonoCache
{
public Dragging dragging;
public Rigidbody2D rb;
public Vector3 position;
public Quaternion rotation;
ObjectManager objectManager;
Transform transform_;
void Start()
{
objectManager = GetComponent<ObjectManager>();
transform_ = transform;
rb = GetComponent<Rigidbody2D>();
}
public override void OnTick()
{
position = transform_.position;
rotation = transform_.rotation;
}
}
I wanted the script to work like this: When an object touches the Player Drawing, it turns on physic and SpriteRenderer, otherwise everything would happen in reverse. BUT IT DOESN'T WORK.
help please
Make sure you don't have any exceptions spamming into the console when you walk.
Also make sure to use the Profiler to see what method-calls are using the most of your framerate, you might have to turn on the deep profiler to see the exact methods.

i have a camera shake script but when i click start it directy goes off and it wont stop

i have a camera shake script but when i click start it directy goes off and it wont stop
in this script i wanted to trigger the shake effect
public class GameOver : MonoBehaviour
{
public Explosion shake;
void OnCollisionEnter2D (Collision2D coll)
{
Debug.Log("Collision!");
if (coll.gameObject.tag == "platform")
{
Destroy(gameObject);
shake.GameOver = true;
}
}
}
and this is the other script
public class Explosion : MonoBehaviour
{
public Transform cameraTransform;
private Vector3 orignalCameraPos;
public float shakeDuration;
public float shakeAmount;
private bool canShake = false;
public bool GameOver = false;
private float _shakeTimer;
void Start()
{
orignalCameraPos = cameraTransform.localPosition;
GameOver = false;
_shakeTimer = 0;
}
void Update()
{
if (GameOver = true)
{
ShakeCamera();
}
}
public void ShakeCamera()
{
_shakeTimer = shakeDuration;
StartCameraShakeEffect();
}
public void StartCameraShakeEffect()
{
if (_shakeTimer > 0)
{
cameraTransform.localPosition = orignalCameraPos + Random.insideUnitSphere * shakeAmount;
_shakeTimer -= Time.deltaTime;
}
else
{
_shakeTimer = 0f;
cameraTransform.position = orignalCameraPos;
GameOver = false;
}
}
}
if you are able to help me i would be very thankfull :)
in the statement if (GameOver = true) you are setting GameOver to true and then checking its value. I think you might have wanted to use if (GameOver == true) or if (GameOver) which will check if this variable is set to true.

Unity 2D 'Attack()' is a local function and must therefore always have a body

I am trying to make a function named "Attack()" that will ocurr diferently if the player is facing a diferent direction in Unity 2D but i am getting the error that i have stated above. I am also getting this error "'Attack' does not exist in the current context" . I am fairly new to Unity so please have patience. Here is the code
` public class PlayerCombat : MonoBehaviour {
public Transform AttackAreaRight;
public float AttackRangeRight = 0.5f;
public float AttackRangeLeft = 0.5f;
public Transform AttackAreaLeft;
public bool IsFacingRight = true;
public bool IsFacingLeft = false;
public LayerMask EnemyLayers;
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
IsFacingRight = false;
IsFacingLeft = true;
Debug.Log("FacingLeft");
}
if (Input.GetKeyDown(KeyCode.D))
{
IsFacingLeft = false;
IsFacingRight = true;
Debug.Log("FacingRight");
}
if (Input.GetKeyDown(KeyCode.F))
{
Attack();
}
if (IsFacingRight = true) ;
{
void Attack()
{
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(AttackAreaRight.position, AttackRangeRight, EnemyLayers);
foreach (Collider2D enemy in hitEnemies)
{
Debug.Log("LMAORight");
}
}
}
if (IsFacingLeft = true) ;
{
void Attack();
{
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(AttackAreaLeft.position, AttackRangeLeft, EnemyLayers);
foreach (Collider2D enemy in hitEnemies)
{
Debug.Log("LMAOLeft");
}
}
}
}
}
`
So there's a few issues here. This is more what you want.
public Transform AttackAreaRight;
public float AttackRangeRight = 0.5f;
public float AttackRangeLeft = 0.5f;
public Transform AttackAreaLeft;
public bool IsFacingRight = true;
public LayerMask EnemyLayers;
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
IsFacingRight = false;
Debug.Log("FacingLeft");
}
if (Input.GetKeyDown(KeyCode.D))
{
IsFacingRight = false;
Debug.Log("FacingRight");
}
if (Input.GetKeyDown(KeyCode.F))
{
Attack();
}
}
void Attack()
{
Vector2 attackPosition;
float attackRange;
if (IsFacingRight)
{
attackPosition = AttackAreaRight.position;
attackRange = AttackRangeRight;
}
else
{
attackPosition = AttackAreaLeft.position;
attackRange = AttackRangeLeft;
}
Collider2D[] hitEnemies = Physics2D.OverlapCircleAll(attackPosition, attackRange, EnemyLayers);
foreach (Collider2D enemy in hitEnemies)
{
Debug.Log("Attacked");
}
}
So the first problem is you declared a function inside a function. Update() is a unity function called every frame so inside of it you can't have a function declared (that what you were doing with void Attack()).
Now if you want to set a value for your character's direction (left/right) its easier to only have 1 boolean so you don't have errors later on like IsLeft bieng true and IsRight being true. Since if IsRight is true than IsLeft must be false and so on.
You can then check this boolean inside the attack function and set the corresponding data for the OverlapCircle.
I'm not sure it is working or not but at least now not giving error on compilation.
If you could test it.
using UnityEngine;
public class PlayerCombat : MonoBehaviour
{
public Transform AttackAreaRight;
public float AttackRangeRight = 0.5f;
public float AttackRangeLeft = 0.5f;
public Transform AttackAreaLeft;
public bool IsFacingRight = true;
public bool IsFacingLeft = false;
public LayerMask EnemyLayers;
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
IsFacingRight = false;
IsFacingLeft = true;
Debug.Log("FacingLeft");
}
if (Input.GetKeyDown(KeyCode.D))
{
IsFacingLeft = false;
IsFacingRight = true;
Debug.Log("FacingRight");
}
if (Input.GetKeyDown(KeyCode.F)){
Attack();
}
}
private void Attack()
{
if (IsFacingLeft == true && IsFacingRight == false)
{
Collider2D[] hitEnemies =
Physics2D.OverlapCircleAll(AttackAreaLeft.position, AttackRangeLeft, EnemyLayers);
foreach (Collider2D enemy in hitEnemies)
{
Debug.Log("LMAOLeft");
}
}
else if (IsFacingRight == true && IsFacingLeft == false)
{
Collider2D[] hitEnemies =
Physics2D.OverlapCircleAll(AttackAreaRight.position, AttackRangeRight, EnemyLayers);
foreach (Collider2D enemy in hitEnemies)
{
Debug.Log("LMAORight");
}
}
}
}

How to pick up object based on pointer position and not player position?

I found a code that works great in my game to pick up an object and throw it but when two objects are next to each other, the game picks both of them at the same time because it is calculated from player's distance to the object.
I tried to understand rays but I can't sort it out...
Here is the code:
using UnityEngine;
using System.Collections;
public class ThrowObject : MonoBehaviour
{
public Transform player;
public Transform playerCam;
public float throwForce = 10;
bool hasPlayer = false;
bool beingCarried = false;
public AudioClip[] soundToPlay;
private AudioSource audio;
public int dmg;
private bool touched = false;
void Start()
{
audio = GetComponent<AudioSource>();
}
void Update()
{
float dist = Vector3.Distance(gameObject.transform.position, Input.mousePosition);
if (dist <= 2.5f)
{
hasPlayer = true;
}
else
{
hasPlayer = false;
}
if (hasPlayer && Input.GetButtonDown("Use"))
{
GetComponent<Rigidbody>().isKinematic = true;
transform.parent = playerCam;
beingCarried = true;
}
if (beingCarried)
{
if (touched)
{
GetComponent<Rigidbody>().isKinematic = false;
transform.parent = null;
beingCarried = false;
touched = false;
}
if (Input.GetMouseButtonDown(0))
{
GetComponent<Rigidbody>().isKinematic = false;
transform.parent = null;
beingCarried = false;
GetComponent<Rigidbody>().AddForce(playerCam.forward * throwForce);
RandomAudio();
}
else if (Input.GetMouseButtonDown(1))
{
GetComponent<Rigidbody>().isKinematic = false;
transform.parent = null;
beingCarried = false;
}
}
}
void RandomAudio()
{
if (audio.isPlaying){
return;
}
audio.clip = soundToPlay[Random.Range(0, soundToPlay.Length)];
audio.Play();
}
void OnTriggerEnter()
{
if (beingCarried)
{
touched = true;
}
}
}
Any help would be gladly appreciated. Thank you in advance!
Have a look at OnMouseOver and OnMouseEnter functions
https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseOver.html

Using code in other class

My code works perfectly in the player class, but when I try to put it in a different class, it does nothing. My player doesn't lose lifes, and he doesn't die.
Here it doesn't work:
Spikes class
using UnityEngine;
using System.Collections;
public class Spikes : MonoBehaviour
{
SimplePlayer0 player = new SimplePlayer0();
Animator anim;
private bool isDead;
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "spike" && !isDead && player.Lives <= 1 && !player.IsImmune)
{
player.Lives = 0;
isDead = true;
}
else if (other.gameObject.tag == "spike" && player.Lives >= 1 && !player.IsImmune)
{
player.Lives--;
anim.SetBool("Immume", true);
player.IsImmune = true;
}
}
void OnTriggerStay2D(Collider2D other)
{
if (other.tag == "spike" && !isDead && player.Lives <= 1 && !player.IsImmune)
{
player.Lives = 0;
isDead = true;
}
else if (other.gameObject.tag == "spike" && player.Lives >= 1 && !player.IsImmune)
{
player.Lives--;
anim.SetBool("Immume", true);
player.IsImmune = true;
}
}
void OnCollisionStay2D(Collision2D other)
{
if (other.gameObject.tag == "spike" && !isDead && player.Lives <= 1 && !player.IsImmune)
{
player.Lives = 0;
isDead = true;
}
else if (other.gameObject.tag == "spike" && player.Lives > 1 && !player.IsImmune)
{
player.Lives--;
anim.SetBool("Immune", true);
player.IsImmune = true;
}
else if (other.gameObject.tag == "Underground")
{
isDead = true;
}
}
void Dead()
{
if (isDead == true)
{
Application.LoadLevel(8);
}
}
}
Player class
using UnityEngine;
using System.Collections;
public class SimplePlayer0 : MonoBehaviour
{
Animator anim;
//Lives
private int lives = 3;
private bool isImmune;
public float immuneCounter;
public float immuneTime;
//PROPERTIES
public int Lives
{
get { return lives; }
set { lives = value; }
}
public bool IsImmune
{
get { return isImmune; }
set { isImmune = value; }
}
void Start ()
{
anim = GetComponent<Animator>();
}
void Update()
{
if (IsImmune)
{
immuneCounter -= Time.deltaTime;
}
if (immuneCounter <= 0)
{
IsImmune = false;
immuneCounter = immuneTime;
anim.SetBool("Immume", false);
}
}
This was the original code where it did work:
using UnityEngine;
using System.Collections;
public class Player0 : MonoBehaviour
{
Animator anim;
//Lives
public int lives = 3;
public bool isImmune;
public float immuneCounter;
public float immuneTime;
public bool isDead;
void Start()
{
anim = GetComponent<Animator>();
}
void Update()
{
if (isImmune)
{
immuneCounter -= Time.deltaTime;
}
if (immuneCounter <= 0)
{
isImmune = false;
immuneCounter = immuneTime;
anim.SetBool("Immume", false);
}
if (isDead == true)
{
Application.LoadLevel(8);
}
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "spike" && !isDead && lives <= 1 && !isImmune)
{
rigidbody2D.velocity = Vector2.zero;
lives = 0;
rigidbody2D.AddForce(new Vector2(0, 200)); // death animation
isDead = true;
}
else if (other.gameObject.tag == "spike" && lives >= 1 && !isImmune)
{
lives--;
anim.SetBool("Immume", true);
isImmune = true;
}
}
void OnTriggerStay2D(Collider2D other)
{
if (other.tag == "spike" && !isDead && lives <= 1 && !isImmune)
{
rigidbody2D.velocity = Vector2.zero;
lives = 0;
rigidbody2D.AddForce(new Vector2(0, 200));
isDead = true;
}
else if (other.gameObject.tag == "spike" && lives >= 1 && !isImmune)
{
lives--;
anim.SetBool("Immume", true);
isImmune = true;
}
else if (other.gameObject.tag == "Underground")
{
rigidbody2D.AddForce(new Vector2(0, 200));
isDead = true;
}
}
void OnCollisionStay2D(Collision2D other)
{
if (other.gameObject.tag == "spike" && !isDead && lives <= 1 && !isImmune)
{
rigidbody2D.velocity = Vector2.zero;
lives = 0;
rigidbody2D.AddForce(new Vector2(0, 200));
isDead = true;
}
else if (other.gameObject.tag == "spike" && lives > 1 && !isImmune)
{
lives--;
anim.SetBool("Immune", true);
isImmune = true;
}
else if (other.gameObject.tag == "Underground")
{
rigidbody2D.velocity = Vector2.zero;
lives = 0;
isDead = true;
}
}
}
My guess is that your "Player" doesn't lose lives, because the object you're subtracting the lives from isn't your player. In your Spikes class, you're creating an all new Player object and decreasing the lives from that object, not your already available one.
What I would do, is have a GameController script, which instantiates the player (and anything else that may be required). That way, you know that you've only got one player object to work with.
For example:
public static class GameController
{
public static Player myOnlyPlayer; // either drag in the editor, or instantiate
}
Then you can use the following to access the object:
public class Spike
{
void OnCollisionEnter2D(Collision2D other)
{
// Do something with:
GameController.myOnlyPlayer.ReduceLifeCount();
}
}
Hope this helps!
Firstly - instantiating subclasses of MonoBehaviour via new is an error in itself - I am referring to SimplePlayer0 player = new SimplePlayer0(); in Spikes.cs. Don't do that.
Secondly - LokiSinclair's answer would work, but using a global variable for storing player and always applying the damage to it is very limiting. We should just check for what has collided with spikes and then decide what to do with it (mind you, my code isn't a really elegant solution either):
using UnityEngine;
using System.Collections;
public class Spikes : MonoBehaviour
{
private void ResolveDamage(Collision2D other){
if (other.gameObject.tag == "player"){
var player = other.gameObject.getComponent<SimplePlayer0>();
if(!player.IsImmune){
player.Lives--;
}
}
}
void OnCollisionEnter2D(Collision2D other)
{
ResolveDamage(other);
}
void OnTriggerStay2D(Collision2D other)
{
ResolveDamage(other);
}
void OnCollisionStay2D(Collision2D other)
{
ResolveDamage(other);
}
}
And your player logic should be contained in Player class - that's just a good design principle to follow:
using UnityEngine;
using System.Collections;
public class SimplePlayer0 : MonoBehaviour
{
Animator anim;
//Lives
private int lives = 3;
private bool isImmune;
public float immuneCounter;
public float immuneTime;
//PROPERTIES
//putting some logic in getters-setters of your properties
public int Lives
{
get { return lives; }
set {
if(lives != value){
lives = value;
if(IsDead){
Dead();
}else{
IsImmune = true;
}
}
}
}
private void Dead()
{
Application.LoadLevel(8);
}
public bool IsImmune
{
get { return isImmune; }
set {
if(isImmune != value){
isImmune = value;
anim.SetBool("Immume", isImmune);
//ternary operator - a shorthand for if-else statement
immuneCounter = isImmune ? immuneTime : 0;
}
}
}
public bool IsDead{
get{
return Lives <= 0;
}
}
void Start ()
{
anim = GetComponent<Animator>();
}
void Update()
{
if (IsImmune)
{
immuneCounter -= Time.deltaTime;
}
if (immuneCounter <= 0)
{
IsImmune = false;
}
}

Categories