Pause collider in Unity - c#

I would like that collider is paused for few seconds at the beginning of the game. I'm using this script on object. Thanks.
public class PickUpObject : MonoBehaviour {
void OnCollisionEnter (Collision Col)
{
if (Col.gameObject.name== "Player")
{
Debug.Log("collision detected");
Destroy(gameObject);
}
}
}

Use a timer to check it.
public class PickUpObject : MonoBehaviour {
public float timer = 10f; //seconds
private void Update()
{
timer -= Time.deltaTime;
}
void OnCollisionEnter (Collision Col)
{
if (Col.gameObject.name== "Player" && timer <= 0f)
{
Debug.Log("collision detected");
Destroy(gameObject);
}
}
}

My prefered method would be to set a _startTime variable with the time the scene started and then use that to check against when needed rather than incremementing a value each frame in a Update method.
private float _delay = 2f;
private float _startTime;
private void Start()
{
_startTime = Time.time;
}
void OnCollisionEnter (Collision col)
{
if(Time.time - _startTime < _delay)
{
//Exit if the time passed is less than the _delay
return;
}
//Else run check against player
if (col.gameObject.name == "Player")
{
Debug.Log("collision detected");
Destroy(gameObject);
}
}

public class PickUpObject : MonoBehaviour {
public float delayTime = 2.0f;
public float currentTime = 0.0f;
private void Update()
{
currentTime += Time.deltaTime;
}
void OnCollisionEnter (Collision Col)
{
if (Col.gameObject.name== "Player" && currentTime > delayTime)
{
delayTime += currentTime;
Destroy(gameObject);
delayTime -= currentTime;
currentTime = 0.0f;
}
}
}

You can use https://docs.unity3d.com/ScriptReference/Time-realtimeSinceStartup.html
and check if it's bigger than 5 :D

Related

Slow down player's speed in air

I am working on a 3D game currently that is based on Unity's Roll-a-Ball tutorial. The problem that I have encountered, is that whenever my player jumps, its speed increases in the air and I don't want that to happen. I tried coming up with a solution but I just couldn't make it work the way I wanted it to. How would I prevent this from happening?
Here is my code if anyone is interested:
public class PlayerController : MonoBehaviour
{
private Rigidbody rb;
private float movementX;
private float movementY;
public int count;
public GameObject player;
bool isGrounded = true;
public TextMeshProUGUI countText;
public GameObject winTextObject;
public float speed = 0;
public float jumpSpeed = 0;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
count = 0;
SetCountText();
winTextObject.SetActive(false);
}
// Update is called once per frame
void Update()
{
}
void OnMove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get<Vector2>();
movementX = movementVector.x;
movementY = movementVector.y;
}
void Jump()
{
if (Input.GetKey(KeyCode.Space) && isGrounded)
{
rb.AddForce(Vector2.up * jumpSpeed, ForceMode.Impulse);
}
}
void FixedUpdate()
{
Jump();
Vector3 movement = new Vector3(movementX, 0f, movementY);
rb.AddForce(movement * speed);
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("PickUp"))
{
other.gameObject.SetActive(false);
count++;
SetCountText();
}
}
void SetCountText()
{
countText.text = "Score: " + count.ToString();
if (count >= 14)
{
winTextObject.SetActive(true);
}
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = true;
Debug.Log("You are colliding with the ground!");
}
}
private void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("Ground"))
{
isGrounded = false;
Debug.Log("You are no longer grounded!");
}
}
}
Use drag to create air resistance:

Unity Mirror, Client is not executing damage Command

I have a script on the Player that gets its target by clicking on them. I check if the players auto attack cooldown is 0 and if the player is in range. After that it should run a Command and damage the enemy mob.
This only happens as it is intended on the host and not on client.
And if I remove the enemy != null check in the CmdDamage function the client just disconnects.
public class PlayerAttacker : NetworkBehaviour
public EnemyScript enemy;
public float timer = 0;
public float timerMax;
private void Start()
{
timer = timerMax;
}
private void Update()
{
if (!isLocalPlayer)
return;
if (Input.GetMouseButtonDown(0))
{
Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 mousePos2d = new Vector2(mousePos.x, mousePos.y);
RaycastHit2D hit = Physics2D.Raycast(mousePos2d, Vector2.zero);
if(hit.collider != null && hit.collider.GetComponent<EnemyScript>() != null)
{
enemy = hit.collider.GetComponent<EnemyScript>();
enemy.target.SetActive(true);
}
}
if (timer <= 0)
{
timer = 0;
BasicAttack();
}
else if(timer > 0)
{
timer -= Time.deltaTime;
}
}
private void BasicAttack()
{
float dist = Vector3.Distance(enemy.transform.position, transform.position);
if(dist < 2.5f)
{
GetComponent<NetworkAnimator>().SetTrigger(Animator.StringToHash("sword slash")); ///SEND TRIGGERS OVER NETWORK
CmdDamage();
timer = timerMax;
}
}
[Command]
private void CmdDamage()
{
if(enemy != null)
enemy.TakeDamage(5);
}
public class EnemyScript : NetworkBehaviour
[SyncVar(hook = "OnHealthChanged")] public float currentHealth; //ADD HP BARS INGAME
public float maxHealth;
[SerializeField] public HealthBar healthBar;
public override void OnStartServer()
{
currentHealth = maxHealth;
}
public void TakeDamage(float amount)
{
if (!isServer)
return;
currentHealth -= amount;
}
Where is your OnHealthChanged -hook implemented? With SyncVars that are hooked, you have to assign changed variable inside hook method. In your case, you have to assign a new value for currentHealth inside OnHealthChanged.
Now your currentHealth is updated only on server.

Why is my function runs twice in OnTriggerStay?

I have a simple game in Unity.
The situation is like if I kill an enemy, it drops a pickupable Health.
In the OnTriggerEnter, I handle the player collision with the health, and if the player misses health, it heals a certain amount. (70 exactly)
When player is standing on the health while at maximum health, it does nothing. But if player got damaged while standing on the health, the health should also be picked up, that is where OnTriggerStay comes in.
There I constantly check if the player needs heeling, if do, do the healing, and destroy the heal object.
My problem is that it runs twice. It heals the amount twice to the player. No matter what I do, the function I call in OnTriggerStay is gonna run twice. Why is that? Anybody knows the solution?
Here is the part of my Player.cs file, and my Heal.cs file:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Player : MonoBehaviour
{
//HP and MANA system
[SerializeField]
private int playerHealth;
[SerializeField]
private int playerMaxHealth = 100;
[SerializeField]
private Transform Healthbar;
private void OnTriggerStay(Collider other)
{
if (other.tag == "Enemy")
{
timer += Time.deltaTime;
if (timer > attackSpeed)
{
Enemy enemy = other.GetComponent<Enemy>();
if (enemy != null)
{
enemy.DamageEnemy(playerDamage);
}
timer = 0.0f;
}
}
if (other.tag == "PatrollingEnemy")
{
timer += Time.deltaTime;
if (timer > attackSpeed)
{
PatrollingEnemy enemy = other.GetComponent<PatrollingEnemy>();
if (enemy != null)
{
enemy.DamageEnemy(playerDamage);
}
timer = 0.0f;
}
}
if (other.tag == "Heal")
{
heal(other, false);
}
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Heal")
{
heal(other, false);
}
else if (other.tag == "HealthPotion")
{
heal(other, true);
}
}
private void heal(Collider other, bool isPotion)
{
dynamic heal;
if (isPotion)
{
heal = other.GetComponent<HealthPotion>();
}
else
{
heal = other.GetComponent<Heal>();
}
if (playerHealth < playerMaxHealth && heal != null)
{
addHealthToPlayer(heal.HealAmount);
Destroy(other.gameObject);
}
}
private void addHealthToPlayer(int amount)
{
playerHealth += amount;
if (playerHealth > playerMaxHealth)
{
playerHealth = playerMaxHealth;
}
rescaleHealthBar();
}
private void rescaleHealthBar()
{
Healthbar.transform.localScale = new Vector3((float)playerHealth / (float)playerMaxHealth, 1.0f, 1.0f);
}
}
public class Heal : MonoBehaviour
{
float timer = 0.0f;
float destroyTimer = 0.0f;
float timeWhenDestroy = 15f;
Vector3 rotation = new Vector3(0, 45, 0);
private int healAmount = 70;
public int HealAmount
{
get
{
return healAmount;
}
}
void Update()
{
timer += Time.deltaTime;
destroyTimer += Time.deltaTime;
if (destroyTimer > timeWhenDestroy)
{
Destroy(this.gameObject);
}
transform.Rotate(rotation * Time.deltaTime);
if (timer < 1.0f)
{
transform.Translate(Vector3.up * Time.deltaTime);
}
if (timer > 1.0f)
{
transform.Translate(-Vector3.up * Time.deltaTime);
}
if (timer > 2.0f)
{
timer = 0.0f;
}
}
}
https://docs.unity3d.com/ScriptReference/Object.Destroy.html
Maybe both your events (Enter & Stay) are fired during that frame ?
https://docs.unity3d.com/ScriptReference/Collider.OnTriggerStay.html
OnTriggerStay is called almost all the frames for every Collider other that is touching the trigger. The function is on the physics timer so it won't necessarily run every frame.

Lose Life when Hit Ground

I was trying to create something like a lava floor in Unity 3D, like when the player falls and hit the ground they start losing life gradually, but my code does nothing.
Can someone help please?
public GameManager manager;
public Slider HealthBar;
public float Health = 100f;
public GameObject Plane;
public float Dmg = 10f;
void Start()
{
HealthBar.maxValue = Health;
HealthBar.value = Health;
}
void Update()
{
}
void OnCollisionEnter(UnityEngine.Collision collision)
{
if (collision.gameObject.tag == "LavaGround")
{
Health -= Dmg;
}
public void TakeDamage(float amnt)
{
Health -= amnt;
if (Health <= 0f)
{
manager.GameOver();
}
float _h = Mathf.Clamp(Health, 0f, 100f);
HealthBar.value = _h;
}
seems that nothing is happening because you are just adjusting the Health value in the
if (collision.gameObject.tag == "LavaGround")
{
Health -= Dmg;
}
Please try to change it as
if (collision.gameObject.tag == "LavaGround")
{
TakeDamage(Dmg);
}
to call TakeDamage method and check if health is below zero and update health bar.

Object is being spammed when it comes to my timeBetweenShot variable, can anyone take a look?

I Have created a 2d stealth game where the enemy fires on the player, only problem is that although the bullets are created and deleted fine on another script, the script itself spams the program with bullets every frame, creating the unwanted result
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HurtPlayer : MonoBehaviour
{
public float timeToShoot;
private float timeToShootCounter;
private bool shot;
private Vector3 moveDirection;
public float timeBetweenShot;
public float timeBetweenShotCounter;
public Transform firePoint;
public GameObject Bullet;
// Use this for initialization
void Start()
{
shot = false;
timeToShootCounter = timeToShoot;
}
// Update is called once per frame
void Update()
{
while (shot == true)
{
StartCoroutine(Delay());
Destroy(GameObject.Find("Bullet"));
timeBetweenShot -= Time.deltaTime;
timeToShoot -= Time.deltaTime;
}
}
IEnumerator Delay()
{
yield return new WaitForSeconds(0.5f);
}
void OnTriggerStay2D(Collider2D other)
{
if (other.gameObject.tag == "player")
{
if (shot == false)
{
if (timeToShoot >= 0f)
{
shot = true;
if (shot == true)
{
shot = false;
Instantiate(Bullet, firePoint.position, firePoint.rotation);
Delay();
if (timeBetweenShot <= 0f)
{
shot = false;
timeToShoot = timeToShootCounter;
timeBetweenShot = timeBetweenShotCounter;
}
}
}
}
}
}
}
What I want is the time betweenshot to work and for the enemy to only shoot once every one or half a second, thanks.
Is this what you are looking for?
IEnumerator ContinuousShoot()
{
// Continuously spawn bullets until this coroutine is stopped
// when the player exits the trigger.
while (true)
{
yield return new WaitForSeconds(1f); // Pause for 1 second.
Instantiate(Bullet, firePoint.position, firePoint.rotation);
}
}
void OnTriggerEnter2D(Collider2D other)
{
// Player enters trigger
if (other.gameObject.CompareTag("player"))
{
StartCoroutine(ContinuousShoot());
}
}
void OnTriggerExit2D(Collider2D other)
{
// Player exits trigger
if (other.gameObject.CompareTag("player"))
{
StopCoroutine(ContinuousShoot());
}
}

Categories