I am making a first person shooter using bullets and I'm trying to find a way to delete the instances when it hits an enemy or the wall but its not working. The way I've done it is to give all the walls and enemy's a tag for specific collision detection but it doesn't seem to be working
for me.
plz help
using UnityEngine;
using TMPro;
public class BulletShoot : MonoBehaviour
{
//bullet
public GameObject bullet;
//bullet force
public float shootForce, upwardForce;
//Gun stats
public float timeBetweenShooting, spread, reloadTime, timeBetweenShots;
public int magazineSize, bulletsPerTap;
public bool allowButtonHold;
int bulletsLeft, bulletsShot;
//Recoil
public Rigidbody playerRb;
public float recoilForce;
//bools
bool shooting, readyToShoot, reloading;
//Reference
public Camera fpsCam;
public Transform attackPoint;
//Graphics
public GameObject muzzleFlash;
public TextMeshProUGUI ammunitionDisplay;
//bug fixing :D
public bool allowInvoke = true;
private void Awake()
{
//make sure magazine is full
bulletsLeft = magazineSize;
readyToShoot = true;
}
private void Update()
{
MyInput();
//Set ammo display, if it exists :D
//if (ammunitionDisplay != null)
//ammunitionDisplay.SetText(bulletsLeft / bulletsPerTap + " / " + magazineSize / bulletsPerTap);
}
private void MyInput()
{
//Check if allowed to hold down button and take corresponding input
if (allowButtonHold) shooting = Input.GetKey(KeyCode.Mouse0);
else shooting = Input.GetKeyDown(KeyCode.Mouse0);
//Reloading
if (Input.GetKeyDown(KeyCode.R) && bulletsLeft < magazineSize && !reloading) Reload();
//Reload automatically when trying to shoot without ammo
if (readyToShoot && shooting && !reloading && bulletsLeft <= 0) Reload();
//Shooting
if (readyToShoot && shooting && !reloading && bulletsLeft > 0)
{
//Set bullets shot to 0
bulletsShot = 0;
Shoot();
}
}
private void Shoot()
{
readyToShoot = false;
//Find the exact hit position using a raycast
Ray ray = fpsCam.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0)); //Just a ray through the middle of your current view
RaycastHit hit;
//check if ray hits something
Vector3 targetPoint;
if (Physics.Raycast(ray, out hit))
targetPoint = hit.point;
else
targetPoint = ray.GetPoint(75); //Just a point far away from the player
//Calculate direction from attackPoint to targetPoint
Vector3 directionWithoutSpread = targetPoint - attackPoint.position;
//Calculate spread
float x = Random.Range(-spread, spread);
float y = Random.Range(-spread, spread);
//Calculate new direction with spread
Vector3 directionWithSpread = directionWithoutSpread + new Vector3(x, y, 0); //Just add spread to last direction
//Instantiate bullet/projectile
GameObject currentBullet = Instantiate(bullet, attackPoint.position, Quaternion.identity); //store instantiated bullet in currentBullet
//Rotate bullet to shoot direction
currentBullet.transform.forward = directionWithSpread.normalized;
//Add forces to bullet
currentBullet.GetComponent<Rigidbody>().AddForce(directionWithSpread.normalized * shootForce, ForceMode.Impulse);
currentBullet.GetComponent<Rigidbody>().AddForce(fpsCam.transform.up * upwardForce, ForceMode.Impulse);
if(currentBullet.gameObject.CompareTag("Enemy"))
{
Destroy(currentBullet.gameObject, 3);
}
if (currentBullet.gameObject.CompareTag("Thing"))
{
Destroy(currentBullet.gameObject, 3);
}
//Instantiate muzzle flash, if you have one
if (muzzleFlash != null)
Instantiate(muzzleFlash, attackPoint.position, Quaternion.identity);
bulletsLeft--;
bulletsShot++;
//Invoke resetShot function (if not already invoked), with your timeBetweenShooting
if (allowInvoke)
{
Invoke("ResetShot", timeBetweenShooting);
allowInvoke = false;
//Add recoil to player (should only be called once)
playerRb.AddForce(-directionWithSpread.normalized * recoilForce, ForceMode.Impulse);
}
//if more than one bulletsPerTap make sure to repeat shoot function
if (bulletsShot < bulletsPerTap && bulletsLeft > 0)
Invoke("Shoot", timeBetweenShots);
}
private void ResetShot()
{
//Allow shooting and invoking again
readyToShoot = true;
allowInvoke = true;
}
private void Reload()
{
reloading = true;
Invoke("ReloadFinished", reloadTime); //Invoke ReloadFinished function with your reloadTime as delay
}
private void ReloadFinished()
{
//Fill magazine
bulletsLeft = magazineSize;
reloading = false;
}
}
I have two things to say.
The first is, it seems a little unnecessary to have a bullet object if you are using raycasting to find where you have hit, but it's alright if you want to do it like that.
The second is that the bullet object is not instant, so when you add forces to the bullet in Shoot(), the bullet still hasn't moved yet. You are then checking if it has collided with anything on the same frame, also in Shoot(), which still means the bullet hasn't moved yet. I would recommend moving the collision detection out of the Shoot() method and into a separate method that I would then call in update(), separately from Input().
Hope this helped :D
Related
I have a physics enabled sphere in my scene and a character that i can move around using WASD. now what i want is that as soon as player hits the ball it should not be physics enabled anymore and move along with player as like the player is holding it in the hands.
What i have tried so far:
i was able to do it but not at all perfect how i want it to be. i tried OnCollisionEnter to detect the collision, i made the sphere a child of the player, i used isKinematic = true as soon as collision is detected and i used Vector3.MoveTowards for the object to follow the position as the player.
I have attached two reference videos below
Reference Clip(The style i am aiming for):https://www.youtube.com/watch?v=fi-GB0RwLr0
MyVersion(This is what i am able to do):https://www.youtube.com/watch?v=JtV11KHY4pU
overall, if you watch the clips you can see how my version is very rigid, stucky, buggy, not so light weight feeling at all. Cut me a slack as well if i did anything way wrong, i started unity like just in the previous month.
This is my Player script through which i am controlling it all
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Player : MonoBehaviour
{
public float MoveSpeed;
[SerializeField]private Rigidbody playerRig;
[SerializeField] private Rigidbody ballRig;
[SerializeField] private GameObject Ball;
[SerializeField] private GameObject heldObj;
private bool isTouching = false;
private Vector3 offset = new Vector3(0, 1, 3);
private Vector3 force;
public float jump;
private bool isGrounded = true;
private void Start()
{
Ball = GameObject.FindGameObjectWithTag("Ball");
ballRig.GetComponent<Rigidbody>();
playerRig.GetComponent<Rigidbody>();
}
void Update()
{
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
playerRig.velocity = new Vector3(x*MoveSpeed, playerRig.velocity.y,z*MoveSpeed);
Vector3 vel = playerRig.velocity;
vel.y = 0;
if (vel.x != 0 || vel.z != 0)
{
transform.forward = vel;
}
if(transform.position.y < -10)
{
GameOver();
}
ReleaseTheBall();
if (isTouching == true)
{
ballRig.transform.position = Vector3.MoveTowards(ballRig.transform.position, playerRig.transform.position, 5f);
}
}
void Jump()
{
force = new Vector3(0, jump, 0);
if (Input.GetKeyDown(KeyCode.Space) && isGrounded == true)
{
isGrounded = false;
playerRig.AddForce(force, ForceMode.Impulse);
}
}
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "Ball" && heldObj == null)
{
ballRig.isKinematic = true;
// ballRig.constraints = RigidbodyConstraints.FreezeRotation;
ballRig.transform.parent = playerRig.transform;
isTouching = true;
Debug.Log(" BALL PICKED UP AND MOVING ");
heldObj = Ball;
}
}
public void ReleaseTheBall()
{
if (Input.GetKeyDown(KeyCode.Space) && heldObj != null)
{
isTouching = false;
heldObj = null;
ballRig.transform.parent = null;
//ballRig.constraints = RigidbodyConstraints.None;
ballRig.isKinematic = false;
//Vector3 forceDirection = new Vector3(playerRig.transform.position.x, 0, playerRig.transform.position.z);
Vector3 rotationDirection = new Vector3(playerRig.transform.rotation.x, playerRig.transform.rotation.y, playerRig.transform.rotation.z);
ballRig.AddForce(new Vector3(transform.position.x,0,transform.position.z) * 5, ForceMode.Impulse);
ballRig.AddTorque(rotationDirection * 1);
Debug.Log("BALL RELEASED");
}
}
public void GameOver()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
i know there could be some very inefficient lines of code here, feel free to call out those lines as well.
So, basically what i want is that i want my player to pick up the ball as soon as it hits it and the ball should move exactly like player as if he is holding the ball in his hands and when i hit the spacebar i want the ball to be released into the direction i am looking(this part is also very tricky for me), what i am trying to do is i want to do exactly like in the refrence clip. Thanks a lot in advance.
one more thing, when i stop pressing any key to move(WASD), my player transform keeps changing values up and down and it slightly starts moving. i mean when i dont press any key, it still kinda moves.
First of all, you have indeed quite a lot of lines that aren't useful in here and that could be optimized.
Anyway, I hope this will do what you want it to do:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
[RequireComponent(typeof(Rigidbody))]
public class Player : MonoBehaviour {
[Header("Movement Setup")]
[Tooltip("Translation speed in m/s")]
[SerializeField] float _TranslationSpeed;
[Tooltip("Rotation speed in °/s")]
[SerializeField] float _RotationSpeed;
[Tooltip("Interpolation speed [0;1]")]
[SerializeField] float _InterpolationSpeed;
[Tooltip("Strength for jumps")]
[SerializeField] float _JumpingStrength;
[Tooltip("Strength for shoots")]
[SerializeField] float _ShootingStrength;
[Header("Other Settings")]
[Tooltip("Where the helded item will be placed")]
[SerializeField] Transform _ContactPoint;
[Tooltip("Which layers should be considered as ground")]
[SerializeField] LayerMask _GroundLayer;
// The player's rigid body
Rigidbody _Rigidbody;
// Is the player on the ground
bool _IsGrounded;
// Rigidbody of what's the player is helding. Null if the player isn't holding anything
Rigidbody _HeldedItemRigidbody;
// Getter to _IsGrounded, return true if the player is grounded
public bool IsGrounded { get { return _IsGrounded; } }
private void Start() {
_Rigidbody = GetComponent<Rigidbody>(); // The player's rigidbody could be serialized
}
void FixedUpdate() {
float horizontalInput, verticalInput;
// Getting axis
horizontalInput = Input.GetAxis("Horizontal");
verticalInput = Input.GetAxis("Vertical");
// Moving toward the x
Vector3 moveVect = transform.forward * _TranslationSpeed * Time.fixedDeltaTime * verticalInput;
_Rigidbody.MovePosition(_Rigidbody.position + moveVect);
// Rotating the player based on the horizontal input
float rotAngle = horizontalInput * _RotationSpeed * Time.fixedDeltaTime;
Quaternion qRot = Quaternion.AngleAxis(rotAngle, transform.up);
Quaternion qRotUpRight = Quaternion.FromToRotation(transform.up, Vector3.up);
Quaternion qOrientationUpRightTarget = qRotUpRight * _Rigidbody.rotation;
Quaternion qNewUpRightOrientation = Quaternion.Slerp(_Rigidbody.rotation, qOrientationUpRightTarget, Time.fixedDeltaTime * _InterpolationSpeed); // We're using a slerp for a smooth movement
_Rigidbody.MoveRotation(qRot * qNewUpRightOrientation);
// This prevents the player from falling/keep moving if there is no input
if (_IsGrounded) _Rigidbody.velocity = Vector3.zero;
_Rigidbody.angularVelocity = Vector3.zero;
if (transform.position.y < -10) GameOver();
if (Input.GetKey(KeyCode.Mouse0) && _HeldedItemRigidbody != null) ShootTheBall();
if (!_IsGrounded) return; // What's below this won't be executed while jumping
if (Input.GetKey(KeyCode.Space)) Jump();
}
void Jump() {
_IsGrounded = false;
_Rigidbody.AddForce(_JumpingStrength * transform.up, ForceMode.Impulse);
}
private void OnCollisionEnter(Collision collision) {
// Checking if the player encountered a ground object
if ((_GroundLayer & (1 << collision.gameObject.layer)) > 0) _IsGrounded = true;
if (collision.gameObject.tag == "Ball") { // this can be improved as tags are error prone
// Setting the item position to contact point
collision.gameObject.transform.position = _ContactPoint.position;
// Getting the rigidbody
_HeldedItemRigidbody = collision.gameObject.GetComponent<Rigidbody>();
// Setting the parent
_HeldedItemRigidbody.transform.parent = transform;
// Setting the body to be kinematic
_HeldedItemRigidbody.isKinematic = true;
// Stopping any movement or rotation
_HeldedItemRigidbody.velocity = Vector3.zero;
_HeldedItemRigidbody.angularVelocity = Vector3.zero;
}
}
public void ShootTheBall() {
// Reverting what's done in OnCollisionEnter
_HeldedItemRigidbody.transform.parent = null;
_HeldedItemRigidbody.isKinematic = false;
// Adding force for the shoot
_HeldedItemRigidbody.AddForce(transform.forward * _ShootingStrength, ForceMode.Impulse);
// Resetting helding item to null
_HeldedItemRigidbody = null;
}
public void GameOver() {
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
You have to add a layer, and set the ground to this new layer.
Set up the variable as you like, don't hesitate to mess up with it a little bit to find what suits you (and don't forget to set up the player's mass (in rigidbody) as well!!)
Exemple of setup for the player script
Last things, you have to add an empty game object to your player which will be where the ball will be placed. I know it's a little bit dirty but place it a bit far from the player (more than the ball's radius) or it will bug. We could do something programatically to fix the ball at a spot and adapt this spot to the ball's radius.
This is an example of player
As you can see, I have the empty "player" gameobject which has the rigidbody, the collider and the player script.
The GFX item which is just the capsule.
If you don't know about this: the player game object is actually on the floor (at the player's feet) so it's better for movements. If you do this, don't forget to adjust the player's capsule collider to fit the GFX.
I also have the contact point.
Forget about the nose stuff, it's just a way to see where the player is facing when you just have a capsule.
If you have any question, feel free to ask.
I made a Gun Script (using YT videos) and a Bullethole GameObject should Instantiate at the Position the RayCast hits an Object. But it is always at 0 0 0. I tried many thing but non work.
GameObject bulletHoleClone = Instantiate(bulletHole, rayHit.point, Quaternion.Euler(0, 180, 0));
Destroy(bulletHoleClone, bulletHoleTime);
Whole Code:
using TMPro;
using UnityEngine;
public class GunScript : MonoBehaviour
{
//Gun Stats
public int damage;
public float timeBetweenShooting, spread, range, reloadTime, timeBetweenShots;
public int magazineSize, bulletsPerTap;
public bool allowHoldButton;
int bulletsLeft, bulletsShot;
private float normalSpread;
//bools
bool shooting, readyToShoot, reloading;
//Graphics
public CameraShake camShake;
public float camShakeStrengh, camShakeDuration;
public GameObject muzzleFlash, bulletHole;
public TextMeshProUGUI text;
public float muzzleFlashTime = 0.1f; //Will be deleted after there is an actual Effect and not a Box
public float bulletHoleTime = 3f;
//Refrences
public Camera fpsCam;
public Transform attackPoint;
private RaycastHit rayHit;
public LayerMask dafuqIsEnemey;
private Rigidbody rb;
private void Awake()
{
rb = GetComponent<Rigidbody>();
bulletsLeft = magazineSize;
readyToShoot = true;
normalSpread = spread;
}
private void Update()
{
MyInput();
//Set Text to BulletAmount
text.SetText(bulletsLeft + " / " + magazineSize);
}
private void MyInput()
{
if (allowHoldButton) shooting = Input.GetKey(KeyCode.Mouse0);
else shooting = Input.GetKeyDown(KeyCode.Mouse0);
if (Input.GetKeyDown(KeyCode.R) && bulletsLeft < magazineSize && !reloading) Reload();
//PewPew
if (readyToShoot && shooting && !reloading && bulletsLeft > 0)
{
bulletsShot = bulletsPerTap;
Shoot();
}
if (rb.velocity.magnitude > 0)
spread = normalSpread * 1.5f;
else spread = normalSpread;
if (Input.GetKey(KeyCode.LeftControl))
spread = normalSpread * 2f;
else spread = normalSpread;
}
private void Shoot()
{
readyToShoot = false;
//Bullets go BRRRRRRRRRR
float x = Random.Range(-spread, spread);
float y = Random.Range(-spread, spread);
//Calculate Direction with Spread
Vector3 direction = fpsCam.transform.forward + new Vector3(x, y, 0);
//Maybe Add that the Ray Isnt coming out of your Head. Instead make it apear on the GunTip
if (Physics.Raycast(fpsCam.transform.position, direction, out rayHit, range, dafuqIsEnemey))
{
Debug.Log(rayHit.collider.name);
if (rayHit.collider.CompareTag("Enemy"))
{
Debug.Log("Hit An Enemy");
//rayHit.collider.GetComponent<ShootingAi>().TakeDamage(damage);
}
}
//Shake Camera
camShake.Shake(camShakeDuration, camShakeStrengh);
//Graphics
GameObject bulletHoleClone = Instantiate(bulletHole, rayHit.point, Quaternion.Euler(0, 180, 0));
GameObject muzzleClone = Instantiate(muzzleFlash, attackPoint.position, Quaternion.identity);
Destroy(muzzleClone, muzzleFlashTime);
Destroy(bulletHoleClone, bulletHoleTime);
Debug.Log(rayHit.point);
bulletsLeft--;
bulletsShot--;
Invoke("ResetShot", timeBetweenShooting);
if (bulletsShot > 0 && bulletsLeft > 0)
Invoke("Shoot", timeBetweenShooting);
}
private void ResetShot()
{
readyToShoot = true;
}
private void Reload()
{
reloading = true;
Invoke("ReloadFinished", reloadTime);
}
private void ReloadFinished()
{
bulletsLeft = magazineSize;
reloading = false;
}
}
You're not hitting anything. You check to see if you hit something, and then spawn a bullet hole even if you didn't hit anything.
If you didn't hit anything, there isn't anywhere to put a bullet hole.
The problem is that you're using the raycast hit as a local variable, which allows you to use it outside of the scope where it's actually valid.
Delete rayHit from your class and define it in the raycast instead, like
out RaycastHit rayHit
then it should only be scoped for the if statement and you'll get a compiler error anywhere it's not valid.
This brings up a larger question about what do you do if it misses an enemy, or which layers you should be raycasting against. Personally I think you'd want to raycast against everything, then you can try to determine what you hit and what that means later. Only other really good alternative would be to raycast against enemies, then repeat that against objects if that misses, but it's a lot of overhead to keep spinning up the raycasting engine. You'd be better off firing against multiple layers and getting the layer off the collider.
PS too your spread is probably way, way too big. For values of spread, 0.01 is half a degree, 0.1 is five degrees, 1 is 45 degrees.
I found the Problem. Just tell the Gun that the Layer "Ground" is also an Enemy. Now it works. Thanks
Basically you need to Transform Direction e.g camTrans.TransformDirection. You can try this way
public class Raytest : MonoBehaviour
{
public Camera fpsCam;
public float maxDistance = 200f;
public bool update = true;
public GameObject objectToSpawn;
private void Update()
{
if(!update) return;
var camTrans = fpsCam.transform;
if (Physics.Raycast(camTrans.position, camTrans.TransformDirection(Vector3.forward), out var hit, maxDistance))
{
Debug.DrawRay(camTrans.position, camTrans.TransformDirection(Vector3.forward) * hit.distance, Color.red);
Debug.Log("Did Hit");
var clone = Instantiate(objectToSpawn, hit.point, Quaternion.Euler(0, 180, 0));
update = false;
}
else
{
Debug.DrawRay(camTrans.position, camTrans.TransformDirection(Vector3.forward) * 1000, Color.white);
Debug.Log("Did not Hit");
}
}
}
After hitting raycast
Hey Guys I've been having a problem lately that I cant seem to solve.
A sprite is supposed to roam around (as it does) while nothing is inside its radius, however if the player moves close to it the sprite should theoretically move towards it and stop roaming.
The sprite doesn't follow the player and cant even see its tag since I cant even see the contents of the "Collider2D[] hits".
using System.Collections.Generic;
using UnityEngine;
public class FireCultist : MonoBehaviour
{
public float moveTimeSeconds; //Time it will take object to move, in seconds.
private float xMax = 10.0f; // The boundaries of the spawn area
private float yMax = 10.0f;
private float xMin = -10.0f; // The boundaries of the spawn area
private float yMin = -10.0f;
public int xDistanceRange; // The max distance you can move at one time
public int yDistanceRange;
private BoxCollider2D boxCollider; //The BoxCollider2D component attached to this object.
private Rigidbody2D rb2D; //The Rigidbody2D component attached to this object.
private float inverseMoveTime; //Used to make movement more efficient.
public Vector2 start;
public Vector2 end;
public bool roam = true;
public Collider2D[] hits;
void Start()
{
boxCollider = GetComponent<BoxCollider2D>();
rb2D = GetComponent<Rigidbody2D>();
inverseMoveTime = 1f / moveTimeSeconds;
InvokeRepeating("RandomMove", 0.0f, 5.0f);
}
void Update()
{
Collider2D[] hits = Physics2D.OverlapCircleAll(transform.position, 10); // returns all colliders within radius of enemy
int i = 0;
while(hits.Length > i)
{
Debug.Log("Sees");
Debug.Log(hits[i]);
i++;
}
followPlayer();
if (roam)
{
Debug.Log("Roam");
transform.position = Vector2.MoveTowards(transform.position, end, inverseMoveTime * Time.deltaTime); //Random move to new position
}
}
public void followPlayer()
{
foreach (Collider2D hit in hits)
{
if (hit.tag == "Player") // if the player is within a radius
{
Debug.Log("Chasing Player");
transform.position = Vector2.MoveTowards(transform.position, GameObject.Find("Prefabs/Player").GetComponent<Transform>().position, inverseMoveTime * Time.deltaTime); // chase player
roam = false;
}
else
{
Debug.Log("Continues");
roam = true; // Continue RandomMove()
}
}
}
public void RandomMove() // gets random coordinates near enemy and moves there
{
float xDistance = Random.Range(-xDistanceRange, xDistanceRange); // check
float yDistance = Random.Range(-yDistanceRange, yDistanceRange);// check
if (xDistance < xMax && xDistance > xMin && yDistance < yMax && yDistance > yMin && roam == true) // If within boundaries of walking space
{
start = transform.position;
end = start + new Vector2(xDistance, yDistance);
Debug.Log("Roaming From : " + start + " To : " + end);
}
}
}
The roaming algorithm works however not too sure about the tag detection.
The script belongs to this enemy object
Player Object Properties
It looks like you are declaring a new hits variable during every update instead of using your class-level variable. This means the variable inside of followPlayer() will never be instantiated, and the information will not be passed between the two methods.
Try this:
void Update()
{
hits = Physics2D.OverlapCircleAll(transform.position, 10);
//...
}
You might also consider attaching a trigger collider to the enemy which sends a notification when the player enters/exits the trigger instead of relying on OverlapCircleAll()
void OnTriggerEnter2D(Collider2D col)
{
if(col.gameObject.tag == "Player"){
roam = false;
}
}
void OnTriggerExit2D(Collider2D col)
{
if(col.gameObject.tag == "Player"){
roam = true;
}
}
Yes, I read through about 30 different similar titles before posting this. However, there wasn't anything relevant to what I need. I'm trying to set my camera's Y-axis to follow the player as it moves through the level; however, I don't want the camera to move up and down whilst jumping so I follow the camera's transform.position.y and NOT the player's.
void Pjump()
{
if (Input.GetKeyDown(KeyCode.Space) && onFloor==true
|| Input.GetKeyDown(KeyCode.W) && onFloor==true)
{
player.velocity = new Vector2(0, jump);
onFloor = false;
isJumping = true; // Static Variable to pass onto CamFollow script
}
}
isJumping is set false inside an OnCollisionEnter2d() and called inside of a FixedUpdate().
Now for the CamFollow script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamFollow : MonoBehaviour
{
private GameObject p1;
private bool isFollow;
[Header("Camera Offset Values")]
[SerializeField]
private float xOff;
[SerializeField]
private float yOff;
void Start()
{
p1 = GameObject.FindWithTag("Player");
isFollow = true;
}
void FixedUpdate()
{
if (isFollow)
{
if (Pmove.isJumping == false) // This code works fine
{
transform.position = new Vector3(p1.transform.position.x + xOff, p1.transform.position.y + yOff,
transform.position.z);
}
if(Pmove.isJumping == true) // This is where the problem is: Y-Axis
{
transform.position = new Vector3(p1.transform.position.x + xOff, transform.position.y + yOff,
transform.position.z);
}
}
}
}
When the player jumps, the player and all non-UI objects vanish until the player touches the ground.
I'm trying to make a 2D Sidescroller in Unity right now and have some problems regarding the enemy.
In theory I want the enemy be destroyed if the player jumps on it's head(upper collider/trigger) and the player loses health if he hits the other collider/trigger.
Well the player loses health when hitting the enemy from the side but it also destroys the enemy and I don't know why.
It isn't even near the deathCollider.
Upper collider tag(isTrigger) : enemyHit
(this one is placed at the top of the enemy)
Bigger center collider tag(isTrigger) : enemy
(this one is under the other collider and encloses the rest of the body)
Sorry can't post an image :/
My onTrigger method in the playerScript looks like this
void OnTriggerEnter2D(Collider2D other){
if (other.tag == "spike") {
GotHit();
}
if (other.tag == "groundTrap") {
InstandDeath();
}
if (other.tag == "enemy") {
//hitEnemy = other.gameObject;
AudioSource.PlayClipAtPoint(hitSound, transform.position, 10.0f);
GotHit();
}
if (other.tag == "enemyHit") {
rigidbody2D.velocity = Vector2.zero;
rigidbody2D.AddForce (jumpVector, ForceMode2D.Force);
//switch animation to 'jump'
anim.SetInteger("AnimationStatePink", 2);
AudioSource.PlayClipAtPoint(jumpSound, transform.position, 10.0f);
Destroy(other.gameObject);
}
}
And the enemyScript only has it's movement
public float enemySpeed;
private Vector3 movement;
public static bool startEnemyMovement = true;
//set walking limits
public float leftLimit, rightLimit;
//adjust scaling
public float scaleX, scaleY;
public float rotateX, rotateY;
public void Start(){
movement = Vector3.left * enemySpeed;
}
public void Update() {
if (startEnemyMovement == true)
EnemyMovement ();
if (PinkPlayerControler.isPaused == true)
startEnemyMovement = false;
else
startEnemyMovement = true;
}
void EnemyMovement(){
if (this.transform.position.x > rightLimit) {
movement = Vector3.left * enemySpeed;
transform.localScale = new Vector3(-scaleX,scaleY,1);
} else if (this.transform.position.x < leftLimit) {
movement = Vector3.right * enemySpeed;
transform.localScale = new Vector3(scaleX,scaleY,1);
}
transform.Translate(movement);
}
Edit:
the GotHit() method looks like this
void GotHit (){
if(Health.gameLives > 1){
Health.gameLives--;
AudioSource.PlayClipAtPoint(hitSound, transform.position, 10.0f);
}
else {
youLose();
}
}
Thanks in advance :)
Chrizzly
I found the reason...you were right - I have a script that gives the player point for defeating an enemy and there was still some test code that destroyed the complete GameObject -.- Thanks for the help :) –