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);
}
Related
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
}
}
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!!
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;
}
}
This is a screenshot of the Input settings in the editor there is no crouch and no left shift to make the player moving faster.
This is my script name character controller. attached to the FPSController(Player).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterController : MonoBehaviour
{
public float moveSpeed = 10.0f;
public float jumpForce = 2.0f;
void Start()
{
}
// Update is called once per frame
void Update ()
{
float translatioin = Input.GetAxis("Vertical") * moveSpeed;
float straffe = Input.GetAxis("Horizontal") * moveSpeed;
translatioin *= Time.deltaTime;
straffe *= Time.deltaTime;
transform.Translate(straffe, 0, translatioin);
if (Input.GetKeyDown("escape"))
{
Cursor.lockState = CursorLockMode.None;
}
transform.Translate(0, jumpForce * Input.GetAxis("Jump") * Time.deltaTime, 0);
}
}
I want to add crouch and left shift for faster moving.
This script is only for controlling the mouse looking around and lock state of the mouse cursor attached to the main camera(Player child).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class camMouseLook : MonoBehaviour
{
Vector2 mouseLook;
Vector2 smoothV;
public float sensitivity = 5.0f;
public float smoothing = 2.0f;
public bool mouseDown = false;
public bool cursorLock = false;
public HandleMouseCursor handleMouseCursor;
GameObject character;
// Use this for initialization
void Start ()
{
if(cursorLock == false)
{
Cursor.lockState = CursorLockMode.None;
handleMouseCursor.setMouse();
}
else
{
Cursor.lockState = CursorLockMode.Locked;
}
character = this.transform.parent.gameObject;
}
// Update is called once per frame
void Update ()
{
if (Input.GetMouseButton(0) && mouseDown == true)
{
MouseLook();
}
else
{
if (mouseDown == false)
{
MouseLook();
}
}
}
private void MouseLook()
{
if (cursorLock == false)
{
Cursor.lockState = CursorLockMode.None;
handleMouseCursor.setMouse();
}
else
{
Cursor.lockState = CursorLockMode.Locked;
}
var md = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
md = Vector2.Scale(md, new Vector2(sensitivity * smoothing, sensitivity * smoothing));
smoothV.x = Mathf.Lerp(smoothV.x, md.x, 1f / smoothing);
smoothV.y = Mathf.Lerp(smoothV.y, md.y, 1f / smoothing);
mouseLook += smoothV;
mouseLook.y = Mathf.Clamp(mouseLook.y, -90f, 90f);
transform.localRotation = Quaternion.AngleAxis(-mouseLook.y, Vector3.right);
character.transform.localRotation = Quaternion.AngleAxis(mouseLook.x, character.transform.up);
}
}
You can change speed of your movement in your CharacterController script.
Just create a variable for crouch speed and multiplay it to your translation vector.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CharacterController : MonoBehaviour
{
public float moveSpeed = 10.0f;
public float crouchSpeed = 20;
public float jumpForce = 2.0f;
void Start()
{
}
// Update is called once per frame
void Update ()
{
float finalMoveSpeed = moveSpeed;
// you can add more IF statements for more actions like walking, running, jumping,...
if(Input.GetKey(KeyCode.KeyCode.LeftShift))
finalMoveSpeed = crouchSpeed ;
float translatioin = Input.GetAxis("Vertical") * finalMoveSpeed ;
float straffe = Input.GetAxis("Horizontal") * finalMoveSpeed ;
translatioin *= Time.deltaTime;
straffe *= Time.deltaTime;
transform.Translate(straffe, 0, translatioin);
if (Input.GetKeyDown("escape"))
{
Cursor.lockState = CursorLockMode.None;
}
transform.Translate(0, jumpForce * Input.GetAxis("Jump") * Time.deltaTime, 0);
}
}
I'm creating a test game because I'm getting ready to create my first game but I want to make sure I get all the simple mechanics down that my first game will require. One of the mechanics that will be included in the game is picking up items if they are a certain distance to you. Sometimes there might be multiple of the same object in the game, I figured the code would work for all coins however that is just not the case. The Debug.Log() only works on one specific coin, how do I make it so it will fire no matter what coin I'm near?
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour {
//Player Variables
public float moveSpeed;
public float jumpHeight;
public float raycastDistanceGround;
public Text moneyText;
private bool isGrounded;
private Rigidbody _rgb;
private GameObject player;
private GameObject[] coin;
private float distanceToCollectCoin;
private float distanceToCoin;
void Start () {
moveSpeed = 7f;
jumpHeight = 9f;
raycastDistanceGround = 0.5f;
isGrounded = true;
_rgb = GetComponent<Rigidbody>();
player = GameObject.FindGameObjectWithTag("Player");
coin = GameObject.FindGameObjectsWithTag("Coin");
distanceToCollectCoin = 2f;
Cursor.lockState = CursorLockMode.Locked;
}
void FixedUpdate () {
IsGrounding();
Move();
Jump();
SetMoneyText();
NearCoin();
}
//Player Moving Mechanics
void Move() {
var moveHorizontal = Input.GetAxis("Horizontal") * moveSpeed * Time.fixedDeltaTime;
var moveVertical = Input.GetAxis("Vertical") * moveSpeed * Time.fixedDeltaTime;
transform.Translate(moveHorizontal, 0f, moveVertical);
if (Input.GetKeyDown(KeyCode.Escape)) {
Cursor.lockState = CursorLockMode.None;
}
}
//Player Jump Mechanics
void Jump() {
var jump = new Vector3(0f, _rgb.position.y, 0f);
if (Input.GetKey(KeyCode.Space) && isGrounded == true) {
for (float i = 0; i <= jumpHeight; i++) {
jump.y += i;
_rgb.AddForce(jump);
}
}
}
void IsGrounding() {
if (Physics.Raycast(transform.position, Vector3.down, raycastDistanceGround)) {
isGrounded = true;
} else {
isGrounded = false;
}
}
void SetMoneyText() {
moneyText.text = ("Money: " + EconomyController.Money);
}
void NearCoin() {
for (int i = 0; i < coin.Length; i++) {
distanceToCoin = Vector3.Distance(coin[i].transform.position, player.transform.position);
}
if (distanceToCoin < distanceToCollectCoin) {
Debug.Log("Near Coin");
}
}
}
Looks like you just bracketed some stuff wrong. You need to move your if-statement into the for-loop. Right now it's only checking the distance for the last coin in the array.
void NearCoin()
{
for (int i = 0; i < coin.Length; i++)
{
distanceToCoin = Vector3.Distance(coin[i].transform.position, player.transform.position);
if (distanceToCoin < distanceToCollectCoin)
Debug.Log("Near Coin");
}
}