when I was watching on YouTube, tutorials about endless runner on part 2, the game object wouldn't disappear when it hits the player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Obstacle : MonoBehaviour
{
public int damage = 1;
public float speed;
private void Update()
{
transform.Translate(Vector2.left * speed * Time.deltaTime);
}
void onTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("rocket"))
{
//rocket takes damage 1
other.GetComponent<rocket>().health -= damage;
Debug.Log(other.GetComponent<rocket>().health);
Destroy(gameObject);
}
}
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class rocket : MonoBehaviour
{
private Vector2 targetPos;
public float Yincrement;
public float speed;
public float maxHeight;
public float minHeight;
public int health = 3;
void Update()
{
if (health <= 0)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
transform.position = Vector2.MoveTowards(transform.position, targetPos, speed * Time.deltaTime);
if (Input.GetKeyDown(KeyCode.UpArrow) && transform.position.y < maxHeight)
{
targetPos = new Vector2(transform.position.x, transform.position.y + Yincrement);
}
else if (Input.GetKeyDown(KeyCode.DownArrow) && transform.position.y > minHeight)
{
targetPos = new Vector2(transform.position.x, transform.position.y - Yincrement);
}
}
}
from this one https://www.youtube.com/watch?v=FVCW5189evI and I'm confused why it didn't work, can someone tell me what is wrong?
if you want to destroy use this, Correct Method to get the game object when collide is: other.gameObject
void onTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("rocket"))
{
//rocket takes damage 1
other.gameObject.GetComponent<rocket>().health -= damage;
Debug.Log(other.gameObject.GetComponent<rocket>().health);
Destory(other.gameObject);
}
}
public class megaStar : MonoBehaviour{
private Rigidbody2D rb;
private Animator _ani;
public bool canAttack = true;
[SerializeField] private Attack _attackObject;
private AudioSource _as;
public checkpoint lastCheckpoint;
public bool isDead = false;
private float _timer = 1.0f;
public float attackTimer = 2.0f;
public GameObject projectile;
public float projectileSpeed = 18.0f;
public Transform projectileAttackPoint;
public float timeDelayForNextShoot = 0.1f;
private float CONST_timeDelayForNextShoot;
// Start is called before the first frame update
void Start(){
CONST_timeDelayForNextShoot = timeDelayForNextShoot;
rb = GetComponent<Rigidbody2D>();
_as = GetComponent<AudioSource>();
_ani = GetComponent<Animator>();
_timer = attackTimer;
}
void Update(){
if (Input.GetKey(KeyCode.W))
{
rb.velocity = new Vector2(0f, 10f);
}
else if (Input.GetKey(KeyCode.S))
{
rb.velocity = new Vector2(0f, -10f);
}
else
{
rb.velocity = new Vector2(0f, 0f);
}
timeDelayForNextShoot -= Time.deltaTime;
if (Input.GetKeyDown(KeyCode.K) && timeDelayForNextShoot <= 0f){
_ani.SetBool("projectileAttack", true);
GameObject go = Instantiate(projectile, projectileAttackPoint.position, projectileAttackPoint.rotation) as GameObject;
go.GetComponent<Rigidbody2D>().velocity = new Vector2(-projectileSpeed, 0.0f);
Destroy(go, 2.0f);
timeDelayForNextShoot = CONST_timeDelayForNextShoot;
canAttack = false;
// new WaitForSeconds(1);
return;
}
}
void FixedUpdate()
{
if (!isDead)
{
Update();
}
else{
rb.velocity = Vector2.zero;
RigidbodyConstraints2D newRB2D = RigidbodyConstraints2D.FreezePositionY;
rb.constraints = newRB2D;
}
}
private void OnCollisionEnter2D(Collision2D collision){
if (collision.gameObject.CompareTag("Enemy"))
{
GetComponent<HitPoints>().TakeDamage(1);
}
}
}
Use SetActive instead of Destroy Function.
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("rocket"))
{
//rocket takes damage 1
other.gameObject.GetComponent<rocket>().health -= damage;
Debug.Log(other.gameObject.GetComponent<rocket>().health);
gameObject.SetActive(false);// it'll Hide GameObject instead of Destroying
// gameObject.SetActive(true);// to show again
}
}
Related
This is my movement script.
public class PlayerMovement : MonoBehaviour
{
// VARIABLES
public float movementSpeed;
public float walkSpeed;
public float runSpeed;
private Vector3 moveDirection;
private Vector3 velocity;
public bool isGrounded;
public float groundCheckDistance;
public LayerMask groundMask;
public float gravity;
// References
public CharacterController controller;
public Animator anim;
PhotonView view;
private void Start()
{
controller = GetComponent<CharacterController>();
anim = GetComponentInChildren<Animator>();
view = GetComponent<PhotonView>();
}
private void Update()
{
if (view.IsMine)
{
Move();
}
}
private void Move()
{
if (view.IsMine)
{
isGrounded = Physics.CheckSphere(transform.position, groundCheckDistance, groundMask);
if(isGrounded && velocity.y < 0)
{
velocity.y = -2f;
}
float moveZ = Input.GetAxis("Vertical");
moveDirection = new Vector3(0, 0, moveZ);
moveDirection = transform.TransformDirection(moveDirection);
if (moveDirection != Vector3.zero && !Input.GetKey(KeyCode.LeftShift))
{
// WALK
Walk();
}
else if(moveDirection != Vector3.zero && Input.GetKey(KeyCode.LeftShift))
{
// RUN
Run();
}
else if(moveDirection == Vector3.zero)
{
// IDLE
Idle();
}
moveDirection *= movementSpeed;
controller.Move(moveDirection * Time.deltaTime);
velocity.y += gravity * Time.deltaTime;
controller.Move(velocity * Time.deltaTime);
}
}
private void Idle() {
if (view.IsMine)
{
anim.SetFloat("Speed", 0, 0.1f, Time.deltaTime);
}
}
private void Walk()
{
if (view.IsMine)
{
movementSpeed = walkSpeed;
anim.SetFloat("Speed", 0.5f, 0.1f, Time.deltaTime);
}
}
private void Run(){
if (view.IsMine)
{
movementSpeed = runSpeed;
anim.SetFloat("Speed", 1, 0.1f, Time.deltaTime);
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
public class SpawnPlayers : MonoBehaviour
{
public GameObject playerPrefab;
public float minX;
public float maxX;
public float minZ;
public float maxZ;
public float minY;
public float maxY;
// Start is called before the first frame update
private void Start()
{
Vector3 randomPosition = new Vector3(Random.Range(minX, maxX), Random.Range(minY, maxY), Random.Range(minZ, maxZ));
player = PhotonNetwork.Instantiate(playerPrefab.name, randomPosition, Quaternion.identity);
}
}
The code above is the join session code
I also have a really basic camera function that just allows the character to look but I don't think anything is wrong with that. The view.IsMine at least makes it so that the users can not control both characters at the same time but it still allows for other person controller and can't control his own character. Is there anyone that knows how to fix this issue?
I am making a 2D camera follow script where if the player enters a collider it will test if that has the layer "waypoint" and if so the camera will go to the center of the gameobject with that collider in a smooth transition; however, when I try to test if the player is colliding with OnCollisionEnter2D it doesn't execute, I also tried OnTriggerEnter2D and that doesn't work either. I tested each with "is trigger" true, and false, and with a rigidbody set to kinematic. the only thing I haven't tried is adding a rigidbody with kinematic false, but I don't want to go through the trouble of having to make physics not effect the player with kinematic true.
Camera script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CamFollow : MonoBehaviour
{
public Transform player;
public Transform playerFrame;
public List<GameObject> waypoints;
private bool hasWaypoints;
private bool inWaypoint;
private int waypointIn;
// Start is called before the first frame update
void Start()
{
hasWaypoints = true;
if (waypoints.Count == 0)
{
hasWaypoints = false;
}
inWaypoint = false;
waypointIn = 0;
}
// Update is called once per frame
void Update()
{
if (hasWaypoints)
{
if (inWaypoint)
Move(waypoints[waypointIn].transform.position);
else
MoveInFrame(player.position);
}
else
{
MoveInFrame(player.position);
}
}
void MoveInFrame(Vector3 moveTo)
{
Vector3 playerFrameRelative = playerFrame.position - transform.position;
transform.position = Vector3.MoveTowards(transform.position, moveTo - playerFrameRelative, 10);
transform.position = new Vector3(transform.position.x, transform.position.y, -10);
}
void Move(Vector3 moveTo)
{
transform.position = Vector3.MoveTowards(transform.position, moveTo, 10);
transform.position = new Vector3(transform.position.x, transform.position.y, -10);
}
public void Coll(Collider2D collision)
{
inWaypoint = true;
waypointIn = waypoints.IndexOf(collision.gameObject);
}
public void setWaypoint(bool b)
{
inWaypoint = b;
}
}
Player script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float speed = 9.53f;
public float jumpPower = 2.46f;
public float gravity = 0.65f;
public bool startsBackwards;
public GameObject camera;
public LayerMask layerMask;
private float upSpeed;
private int jumps;
private RaycastHit2D hit;
private Vector3 direction;
void Start()
{
if (startsBackwards)
direction = Vector3.left;
else
direction = Vector3.right;
}
void Update()
{
if (jumps < 3)
{
if (Input.GetKeyDown("w") || Input.GetKeyDown("up") || Input.GetKeyDown("space"))
{
upSpeed = jumpPower + gravity;
jumps--;
}
}
transform.Translate(direction * speed * Time.deltaTime);
upSpeed = upSpeed - gravity;
if (upSpeed < 0)
{
hit = Physics2D.BoxCast(transform.position, new Vector2(1, 1), 0, Vector2.down, -upSpeed, layerMask.value);
if (hit)
{
transform.Translate(Vector3.down * hit.distance);
jumps = 0;
upSpeed = 0;
}
else
transform.Translate(Vector3.up * upSpeed);
}
if (upSpeed > 0)
{
//hit = Physics2D.BoxCast(transform.position, new Vector2(1, 1), 0, Vector2.up, upSpeed);
if (false)
transform.Translate(Vector3.up * hit.distance);
else
transform.Translate(Vector3.up * upSpeed);
}
}
void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Reverse")
{
if (direction == Vector3.right)
direction = Vector3.left;
else
direction = Vector3.right;
}
if (camera.GetComponent<CamFollow>().waypoints.Contains(collision.gameObject))
camera.GetComponent<CamFollow>().Coll(collision);
else
camera.GetComponent<CamFollow>().setWaypoint(false);
Debug.Log("worked!");
}
}
Help me please!!
In my game I want to have a floating monster that's attack throws a grenade at the player. My problem is that the grenade only spawns in 0, 0, 0. In my script I make it so that the zombies spawns in on its own location but for some reason that doesn't work. I tried making it spawn by having the spawn location equal new Vector3(100, 100, 100) but it still spawned at 0, 0, 0. I know that the co-routine runs because I put a Debug.Log. Thanks for the help!
Edit #2: I can't have a rigidbody on the script. I have edited the movement script and I have found that no mater what if a rigidbody is added then it will go to 0, 0, 0.
Edit #3: I updated the scripts
Here is my script: (Sorry if the code is bad)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ZKAttack_lvl3 : MonoBehaviour
{
public Transform Player;
public float MoveSpeed = 2.0f;
public float InRadius = 10.0f;
public float AttackRange = 15.0f;
private Coroutine hasCourutineRunYet;
public GameObject grenade;
public GameObject FloatingMonster;
private Vector3 FloatingMon;
private Animator anim;
private Rigidbody rigid;
private void Start()
{
anim = GetComponent<Animator>();
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
rigid = GetComponent<Rigidbody>();
}
void Update()
{
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
transform.LookAt(Player);
float dstSqr = (Player.position - transform.position).sqrMagnitude;
bool inRadius = (dstSqr <= InRadius * InRadius);
bool inAttackRange = (dstSqr <= AttackRange * AttackRange);
anim.SetBool("AttackingPlayer", inAttackRange);
if (inRadius)
{
transform.position += transform.forward * MoveSpeed * Time.deltaTime;
}
rigid.AddForce(1, 10, 1);
if (inAttackRange)
{
if (hasCourutineRunYet == null)
{
hasCourutineRunYet = StartCoroutine(GrenadeAttack());
}
}
}
IEnumerator GrenadeAttack()
{
FloatingMon = FloatingMonster.transform.position;
GameObject bulletObject = Instantiate(grenade, FloatingMonster.transform.position, Quaternion.identity);
yield return new WaitForSeconds(2.0f);
}
}
Edit: This is the code for the movement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GrenadeMovement : MonoBehaviour
{
public float speed = 10f;
public float lifeDuration = 4.0f;
private float lifeTimer;
private Coroutine hasCourutineRunYet;
private Transform Player;
public SphereCollider sphereCollider;
// Use this for initialization
void Start()
{
lifeTimer = lifeDuration;
sphereCollider.enabled = false;
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
}
// Update is called once per frame
void Update()
{
lifeTimer -= Time.deltaTime;
if (lifeTimer >= 3f)
{
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
transform.LookAt(Player);
transform.position += transform.forward * speed * Time.deltaTime;
}
if (lifeTimer >= 0f)
{
transform.position = speed * transform.up * Time.deltaTime;
transform.position = speed * transform.forward * Time.deltaTime;
}
if (lifeTimer <= 0f)
{
if (hasCourutineRunYet == null)
{
hasCourutineRunYet = StartCoroutine(GrenadeExplosion());
}
}
}
private void OnTriggerEnter(Collider coll)
{
if (coll.gameObject.tag == "Player")
{
if (hasCourutineRunYet == null)
{
hasCourutineRunYet = StartCoroutine(GrenadeExplosion());
}
}
}
IEnumerator GrenadeExplosion()
{
sphereCollider.enabled = true;
yield return new WaitForSeconds(1.0f);
Destroy(gameObject);
}
}
With the help of #ken I figured out that I couldn't use a rigidbody so I changed the insantiation to this: GameObject bulletObject = Instantiate(grenade, FloatingMonster.transform.position, Quaternion.identity);. I then changed the movement script for it to:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GrenadeMovement : MonoBehaviour
{
public float speed = 10f;
public float lifeDuration = 4.0f;
private float lifeTimer;
private Coroutine hasCourutineRunYet;
private Transform Player;
public SphereCollider sphereCollider;
public Vector3 velocity;
// Use this for initialization
void Start()
{
lifeTimer = lifeDuration;
sphereCollider.enabled = false;
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
}
// Update is called once per frame
void Update()
{
lifeTimer -= Time.deltaTime;
if (lifeTimer >= 2f)
{
Player = GameObject.FindGameObjectsWithTag("Player")[0].transform;
transform.LookAt(Player);
transform.position += transform.forward * 5 * Time.deltaTime;
}
if (lifeTimer >= 0f && lifeTimer <= 2f)
{
transform.position = 9.18f * transform.up * Time.deltaTime;
transform.position = 9.18f * transform.forward * Time.deltaTime;
}
if (lifeTimer <= 0f)
{
if (hasCourutineRunYet == null)
{
hasCourutineRunYet = StartCoroutine(GrenadeExplosion());
}
}
}
private void OnTriggerEnter(Collider coll)
{
if (coll.gameObject.tag == "Player" || coll.gameObject.tag == "Terrain")
{
if (hasCourutineRunYet == null)
{
hasCourutineRunYet = StartCoroutine(GrenadeExplosion());
}
}
}
IEnumerator GrenadeExplosion()
{
sphereCollider.enabled = true;
yield return new WaitForSeconds(1.0f);
Destroy(gameObject);
}
}
Thank you for all your help, I have been trying to fix this all week.
You could set its position in the Instantiate line. Instantiate has several arguments. You can set its position in Instantiate, as well as its rotation and parent.
Set it to this:
IEnumerator GrenadeAttack()
{
GameObject bulletObject = Instantiate(grenade, FloatingMonster.transform.position, Quaternion.identity);
yield return new WaitForSeconds(2.0f);
}
I was testing out scripts and there was a bug, that output 0 as its Rigidbody.velocity.y only if it goes up (so when the random chance it goes down it doesn't break), until it becomes negative (collision with resitution 1 or mirror bouncy) which then output a nonzero integer, so working as normal.
Edit: The temporary solution is just to remove the if statement in if (rb.velocity.y != 0) but i wanna know why does it output 0
Edit2: Maybe its a Unity bug, and i am in Unity 2019.4, so updating might be the solution? So if the "bug" dissapears, im sorry for wasting your time
First code determines the ball, while the second determines the ai
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallMovement : MonoBehaviour
{
public float speed;
public Rigidbody2D rb;
public Vector3 startPosition;
public float rampSpeed;
private float startSpeed;
public float tempSpeed;
// Start is called before the first frame update
void Start()
{
startPosition = transform.position;
startSpeed = speed;
Launch();
}
// Update is called once per frame
void Update()
{
}
private void Launch()
{
float x = Random.Range(0,2) == 0 ? -1 : 1;
float y = Random.Range(0,2) == 0 ? -1 : 1;
rb.velocity = new Vector2(speed * x, speed * y);
}
private void OnCollisionEnter2D ()
{
tempSpeed = speed;
speed += rampSpeed;
rb.velocity = new Vector2(rb.velocity.x*speed/tempSpeed,rb.velocity.y*speed/tempSpeed);
GetComponent<AudioBall>().SoundCollision();
}
public void Reset()
{
rb.velocity = Vector2.zero;
transform.position = startPosition;
speed = startSpeed;
Launch();
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public bool isPlayer1;
public float speed;
public float moveInput;
private Rigidbody2D rb;
public Vector3 startPosition;
//AI
[Header("Ball")]
public GameObject ball;
private Rigidbody2D rbBall;
private float sign;
public bool ActivateAI;
public bool TurnOnOveride;
// Start is called before the first frame update
void Start()
{
if (TurnOnOveride == false)
{
ActivateAI = PlayMenu.ActivateAI;
}
else
{
ActivateAI = true;
}
startPosition = transform.position;
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if(ActivateAI == false || isPlayer1 == true)
{
//this part is just human control. dont mind this
if (isPlayer1 == true)
{
moveInput = Input.GetAxisRaw("Vertical");
}
else
{
moveInput = Input.GetAxisRaw("Vertical2");
}
}
//AI
else
{
rbBall = ball.GetComponent<Rigidbody2D>();
sign = Mathf.Sign(rbBall.velocity.y);
Debug.Log("sign:"+sign);
if (sign == -1)
{
moveInput = -1;
}
else
{
Debug.Log("rb.y:"+rb.velocity.y);
if (rb.velocity.y != 0)
{
moveInput = 1;
}
}
}
rb.velocity = new Vector2(rb.velocity.x, moveInput * speed);
}
public void Reset()
{
rb.velocity = Vector2.zero;
transform.position = startPosition;
}
}
I have both player and ground with colliders 2D and player is supposed to stop on top of ground but instead it stops at the bottom of the ground.
Code
PlayerController
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
private float moveSpeedStore;
public float speedMultiplier;
public float speedIncreateMilestone;
private float speedIncreateMilestoneStore;
private float speedMilestoneCount;
private float speedMilestoneCountStore;
public float jumpForce;
public float jumpTime;
private float jumpTimeCounter;
private bool stoppedJumping;
private bool canDoubleJump;
private Rigidbody2D myRigidbody;
public bool grounded;
public LayerMask whatIsGround;
public Transform groundCheck;
public float groundCheckRadius;
// private Collider2D myCollider;
private Animator myAnimator;
public GameManager theGameManager;
public AudioSource jumpSound;
public AudioSource deathSound;
// Start is called before the first frame update
void Start()
{
myRigidbody = GetComponent<Rigidbody2D>();
myAnimator = GetComponent<Animator>();
jumpTimeCounter = jumpTime;
speedMilestoneCount = speedIncreateMilestone;
moveSpeedStore = moveSpeed;
speedMilestoneCountStore = speedMilestoneCount;
speedIncreateMilestoneStore = speedIncreateMilestone;
stoppedJumping = true;
}
// Update is called once per frame
void Update()
{
grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, whatIsGround);
if(transform.position.x > speedMilestoneCount)
{
speedMilestoneCount += speedIncreateMilestone;
speedIncreateMilestone = speedIncreateMilestone * speedMultiplier;
moveSpeed = moveSpeed * speedMultiplier;
}
myRigidbody.velocity = new Vector2(moveSpeed, myRigidbody.velocity.y);
if(Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0) )
{
if(grounded)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, jumpForce);
stoppedJumping = false;
jumpSound.Play();
}
if(!grounded && canDoubleJump)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, jumpForce);
jumpTimeCounter = jumpTime;
stoppedJumping = false;
canDoubleJump = false;
jumpSound.Play();
}
}
if((Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0)) && !stoppedJumping)
{
if(jumpTimeCounter > 0)
{
myRigidbody.velocity = new Vector2(myRigidbody.velocity.x, jumpForce);
jumpTimeCounter -= Time.deltaTime;
}
}
if(Input.GetKeyUp(KeyCode.Space) || Input.GetMouseButtonUp(0))
{
jumpTimeCounter = 0;
stoppedJumping = true;
}
if(grounded)
{
jumpTimeCounter = jumpTime;
canDoubleJump = true;
}
myAnimator.SetFloat("Speed", myRigidbody.velocity.x);
myAnimator.SetBool("Grounded", grounded);
}
void OnCollisionEnter2D(Collision2D other) {
if(other.gameObject.tag == "killbox")
{
theGameManager.RestartGame();
moveSpeed = moveSpeedStore;
speedMilestoneCount = speedMilestoneCountStore;
speedIncreateMilestone = speedIncreateMilestoneStore;
deathSound.Play();
}
}
}
Player settings
Question
What should I do to hold my player on top of ground?
NOTE: it's my first question on unity ever so if you need any sort of code or data please just ask, I try my best to provide you what you need.
Thanks.
It looks like your collider is simply too high. You'll notice that the green box indicating your collider size and position is colliding with the correct spot on the ground. The bottom of it is just touching the top of the ground. You simply need to move the collider down on the player so that the bottom of the green box is at the bottom of the player's sprite.