I have a problem with the enemy in my game. The enemy goes to the left and I want if the player jumps on the enemy then the enemy dies. Or if the enemy collides with the player on the side then the player dies. I made the script only atttached on the enemy. But if the enemy collides on the side the player dies and if I jump on the enemy the player still dies.
Here is the code of the enemy:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyMovement : MonoBehaviour
{
public float range = 10f; // the range at which the enemy will start moving towards the player
public float speed = 5f; // the speed at which the enemy will move
private Transform player; // reference to the player's transform
private Rigidbody2D rb; // reference to the enemy's Rigidbody2D component
void Start()
{
// find the player's transform by finding the object with the "Player" tag
player = GameObject.FindGameObjectWithTag("Player").transform;
// get the enemy's Rigidbody2D component
//rb = GetComponent<Rigidbody2D>();
}
void Update()
{
// calculate the distance between the enemy and the player
float distance = Vector2.Distance(transform.position, player.position);
// if the distance between the enemy and the player is less than the range
if (distance < range && Pause.IsPause == false)
{
// move the enemy towards the player at the specified speed
transform.position += Vector3.left * speed * Time.deltaTime;
distance = Vector2.Distance(transform.position, player.position);
if (distance > range)
{
Destroy(gameObject);
}
}
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Player")
{
// The enemy has collided with the player
if (collision.relativeVelocity.y > 0 && transform.position.y < collision.transform.position.y)
{
// The player is colliding with the top of the enemy from above
// Destroy the enemy game object
Destroy(gameObject);
}
else
{
// The player is colliding with the side or bottom of the enemy, or the player is not colliding with the top of the enemy from above
// Destroy the player game object
Destroy(collision.gameObject);
}
}
}
}
ChatGPT helped me but it failed with the colliders. Can somebody help me please?
If Collision.relativeVelocity works the way I think it does, that means you need to replace collision.relativeVelocity.y > 0 with collision.relativeVelocity.y < 0.
If the relativeVelocity is based on the reference frame of the enemy, then it is the velocity of the player relative to the enemy. If the player's relative velocity is > 0, then the player would still be rising, not falling. This means the code will never run if the player is falling. Changing it to < 0 makes it so the code will only run if the player IS falling.
You can test my assumption using Debug.Log(collision.relativeVelocity.y) when you collide with the top. If y is negative, then it's true.
Related
I am trying ground collision of kinematic bodies using rigidbody2D.cast. Player and ground collider overlap with each other.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ForceMethod : MonoBehaviour
{
[SerializeField] Vector2 worldGravity;
[SerializeField] float downCastDistance = 0.05f;
Vector2 startingVelocity = new Vector2(0, 0);
RaycastHit2D[] hits = new RaycastHit2D[2];
Rigidbody2D rb;
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
void Update()
{
rb.Cast(Vector2.down, hits, downCastDistance);
}
void FixedUpdate()
{
rb.MovePosition(rb.position + startingVelocity * Time.deltaTime);
startingVelocity += worldGravity * Time.deltaTime;
if (hits[0].collider.name == "Ground")
{
rb.MovePosition(rb.position);
}
}
}
Before
After
rb.MovePosition(rb.position);
does nothing, since moves the rb in its current same position.
What you want to do probably is check before moving the rb if the cast hits the ground, but cast in the fixed update as well, and not of a fixed downCastDistance but cast by the same distance the rb will travel downward (which is startingVelocity * Time.deltaTime). If it doesn't hit then go down normally as you did, if it does, move the rb to the highest position between the normal fall update and the position of the point where the raycast hit (which is at ground level):
//FixedUpdate()
float currTravelDistance = startingVelocity.y * Time.deltaTime;
rb.Cast(Vector2.down, hits, Mathf.Abs(currTravelDistance));
if (hits[0].collider.name == "Ground")
{
rb.position.y = Mathf.Max((rb.position + currTravelDistance).y, hits[0].point.y);
}
else {
rb.MovePosition(rb.position + currTravelDistance);
}
also since this moves the rb exactly on the ground, if the rb's center is in the middle of the sprite, move it up by the distance from the sprite's "feet" to its center.
Finally if the player hits the ground you also need to reset to 0 startingVelocity
using UnityEngine;
using System.Collections;
using System;
public class TurretScript : MonoBehaviour
{
public float rangeToPlayer;
public GameObject bullet;
// public GameObject spherePrefab;
private GameObject player; // Tag for DynamicWaypointSeek
private bool firing = false; //Firing status
private float fireTime; // Fire Time
private float coolDown = 1.00F; // Time to cool down fire
private int health = 5; //Health of turret
private bool bDead;
private Action cur;
void Start()
{
player = GameObject.FindWithTag("Player");
bDead = false;
}
void Update()
{
if (PlayerInRange())
{ // PlayerInRange is bool function defined at the end
transform.LookAt(player.transform.position); //Rotates the transform (weapon) so the forward vector points at /target (Player)/'s current position
RaycastHit hit;
if (Physics.SphereCast(transform.position, 0.5F, transform.TransformDirection(Vector3.forward), out hit))
{ //The center of the sphere at the start of the sweep,The radius of the sphere,The direction into which to sweep the sphere.
if (hit.transform.gameObject.tag == "Player")
{ //information in hit (only interested in "Player")
if (firing == false)
{
firing = true;
fireTime = Time.time; //keep the current time
GameObject bul;
Quaternion leadRot = Quaternion.LookRotation(player.transform.position); //Calculate the angular direction of "Player";
bul = Instantiate(bullet, transform.position, leadRot) as GameObject; // existing object to be copied, Position of Copy, Orientation of Copy
//Destroy(bullet, 2.0f);
}
}
}
}
if (firing && fireTime + coolDown <= Time.time) // prvious time stored in fireTime + cool down time is less --> means the firing must be turn off
firing = false;
// Destroy(GameObject.FindGameObjectWithTag("Bullet"));
if (health <= 0)
cur = Deadstate;
}
protected void Deadstate()
{
if (!bDead)
{
bDead = true;
Explode();
}
}
void Explode()
{
Destroy(gameObject, 1.5f);
}
bool PlayerInRange()
{
return (Vector3.Distance(player.transform.position, transform.position) <= rangeToPlayer); //Vector3.Distance(a,b) is the same as (a-b).magnitude.
}
void OnTriggerEnter(Collider col)
{
HealthBarScript.health -= 10f;
}
}`
This is code I wrote for a enemy turret in my current unity project. The idea is that it will fire a bullet at the player once it's in range and stop when it's out of range and when the bullet collides with the player, the player will take damage, but I'm struggling to figure out why the bullet won't do any damage. Thoughts? Very much appreciate the help!
According to my experience: bullet speed may be too fast to detect collision.
Imagine that in 2d:
frame 1:
.BB.......OOO......
frame 2:
........BBOOO......
frame 3:
..........OOO..BB..
Where OOO is your object and BB is your bullet.
To fix this you can have a bigger collider for the bullet. Other workaround like "dynamic" collider are also possible.
I have a ball on a ground, and when touching the screen I want to shoot it to the X position of the Touch. Do you have any suggestions?
This is the code I have so far:
public Rigidbody Ball;
public float Speed = 50f;
void FixedUpdate () {
if(ClickDone == false){
if (Input.GetMouseButton(0)){
ClickDone = true;
Ball.velocity = transform.forward * Speed;
}
}
}
here is your new code :
using UnityEngine;
public class GoToTouch : MonoBehaviour
{
public Camera cam;//put your main camera here
public float speed;//Speed of movement
Vector3 LastTouch;
void Start()
{
LastTouch = Vector3.zero;
}
void Update()
{
//We check for new touches etch frame
if (Input.touchCount> 0)
LastTouch = Input.touches[0].rawPosition;
//We move towards the last touch
if(LastTouch != Vector3.zero)transform.position=
Vector3.Lerp(transform.position,cam.ScreenToWorldPoint(LastTouch),speed*Time.DeltaTime);
}
}
what is important for you to look at is the
ScreenToWorldPoint function LastTouch holds the actual pixel the user touched
after ScreenToWorldPoint you get the position that the pixel he touched represent in the
world. Good luck learning !
I want to do two parts with the script:
When the player is exiting a door trigger action.
When the action is tirggered make the npc slowly rotating facing the player and start moving to the player.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
public class SpaceshipCutscene : MonoBehaviour
{
public Transform player;
public Transform npc;
public float cutsceneDistance = 5f;
public float speed;
private bool moveNpc = false;
// Use this for initialization
void Start()
{
}
private void Update()
{
if (moveNpc)
{
float travel = Mathf.Abs(speed) * Time.deltaTime;
Vector3 direction = (player.position - npc.position).normalized;
Quaternion lookrotation = Quaternion.LookRotation(direction);
npc.rotation = Quaternion.Slerp(npc.rotation, lookrotation, Time.deltaTime * 5);
Vector3 position = npc.position;
position = Vector3.MoveTowards(position, player.position, travel);
npc.position = position;
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject.name == "Horizontal_Doors_Kit")
moveNpc = true;
}
}
It's never getting to the moveNpc = true; line.
The player have a Rigidbody.
In the screenshot it's the player inspector. The soldier is not the player !
The player is a first person.
The soldier should rotate slowly facing the player and start moving to the player when the player exit the door.
The script is attached to the Spaceship GameObject:
The door have some childs and this is the one with the box collider:
That's why in the script I'm checking against the Horizontal_Doors_Kit since this doors child have the box collider.
But it's never getting to the line:
moveNpc = true;
I used a break point on this line.
The problem is seems to be at least from my test is that the script with the OnTriggerExit must be attached to the player and not to some empty GameObject ( Spaceship ). Once the script is attached to the player the trigger is working. I thought that the OnTriggerExit can be trigger from any object but it was my mistake.
SCENERIO
I have a an sphere with sphere collider and another prefab with rigid body problem is that when i am moving the sphere on touch then sphere donot detroy after the collision with falling rigibody object.Sphere only detory when i donot move the object then it collide with the falling rigidbody object.
The Code attach with sphere
using UnityEngine;
using System.Collections;
public class moving : MonoBehaviour {
float speed=100f;
public GameObject hero;
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.touchCount > 0) {
// The screen has been touched so store the touch
Touch touch = Input.GetTouch (0);
if (touch.phase == TouchPhase.Stationary || touch.phase == TouchPhase.Moved) {
// If the finger is on the screen, move the object smoothly to the touch position
Vector3 touchPosition = Camera.main.ScreenToWorldPoint (new Vector3 (touch.position.x, touch.position.y, 100));
transform.position = Vector3.Lerp (transform.position, touchPosition, Time.deltaTime * speed);
}
}
}
void OnCollisionEnter(Collision coll){
Debug.Log(coll.gameObject.name);
if (coll.gameObject.name == "Cube(Clone)") {
Debug.Log(coll.gameObject.name);
Destroy (hero);
}
}
}
The Code Attach With Falling rigibody body object
void Start () {
InvokeRepeating ("spawn", delay, clone_delay);
}
void spawn () {
Instantiate (cube, new Vector3 (Random.Range (6, -6), 10, 0), Quaternion.identity);
}