When i shoot my bullet it chases the enemy. I want to have an aiming system,
for example, the bullet should go to the enemy's position when it was first seen (not chasing object, just shoot to the first position the enemy was seen).
This is my code and it makes the bullet follow the enemy:
void shoot() {
GameObject bulletGO=(GameObject) Instantiate(BulletPrefab, firepoint.position, firepoint.rotation);
Bullet bullet = bulletGO.GetComponent<Bullet>();
if (bullet != null) {
bullet.Seek(target);
}
and :
private Transform target;
public float speed = 5f;
public GameObject ImpactEffect;
public void Seek(Transform _target) {
target = _target;
}
// Update is called once per frame
void Update () {
if (target == null)
{
Destroy(gameObject);
return;
}
Vector3 dir = target.position - transform.position;
float distancethisframe = speed * Time.deltaTime;
if (dir.magnitude <= distancethisframe)
{
HitTarget();
return;
}
transform.Translate(dir.normalized * distancethisframe, Space.World);
}
so any idea?
Replace
private Transform target;
//...
public void Seek(Transform _target) {
target = _target;
}
//...
Vector3 dir = target.position - transform.position;
with
private Vector3 target;
//...
public void Seek(Transform _target) {
target = _target.position;
}
//...
Vector3 dir = target - transform.position;
That way you caluclate and copy existing target position in Seek and make bullet fly to that position, even if actual target move away. The code you had actually took current target position each time the Update was called.
Related
I'm trying to get an object to always be "in front" of the player, from a top down perspective. Here's screenshots demonstrating what I'm trying to do.
So as you can see, when the blue capsule (player) picks up the green capsule (item), the item correctly hovers in front of the player (indicated by the z-axis blue arrow), but when the player turns in any other direction, the item doesn't follow, and instead stays in exactly the same position relative to the player.
My player controller script looks as follows:
using UnityEngine;
public class PlayerController : MonoBehaviour {
public float movementSpeed = 10;
private Rigidbody body;
private Vector2 movement;
void Start() {
body = GetComponent<Rigidbody>();
}
void Update() {
movement.x = Input.GetAxis("Horizontal");
movement.y = Input.GetAxis("Vertical");
}
void FixedUpdate() {
body.velocity = new Vector3(movement.x * movementSpeed * Time.deltaTime, 0, movement.y * movementSpeed * Time.deltaTime);
// this is what updates the direction of the blue arrow in the direction of player movement
if(movement.x != 0 || movement.y != 0) {
body.rotation = Quaternion.LookRotation(body.velocity);
}
}
}
And here's my pickup script (where the item's position is supposed to be updated):
using UnityEngine;
public class Pickup : MonoBehaviour {
private GameObject item;
public float carryDistance = 1;
void OnCollisionEnter(Collision collision) {
if(collision.gameObject.CompareTag("Item")) {
item = collision.gameObject;
}
}
void Update() {
if(item) {
item.transform.position = transform.position + new Vector3(0, 0, carryDistance);
}
}
}
So to reiterate my question: How can I update the item's position such that it's always hovering next to the player on the side of the blue arrow?
You can achieve this by using players transform.forward
item.transform.position = transform.position + (transform.forward * carryDistance)
+ (Vector3.up * carryHeight);
Alternatively you can just add empty child gameobject to the player, position it in front of the player and use its transform position and rotation to position the picked up object.
public class Pickup : MonoBehaviour {
public Transform pickupPositionTransform;
private GameObject item;
public float carryDistance = 1;
void OnCollisionEnter(Collision collision) {
if(collision.gameObject.CompareTag("Item")) {
item = collision.gameObject;
}
}
void Update() {
if(item) {
item.transform.position = pickupPositionTransform.position;
item.transform.rotation = pickupPositionTransform.rotation;
}
}
}
So i have a simple scene in unity, a player with a parallax background and a Tilemap as a ground, as well as some very simple post processing. I know this isn't a The minute i move, there is a consistent stutter just under ever second. I'm not sure whether it's to do with my player movement code, camera movement or anything else. I'm also using a Cinemachine virtual camera. My rigidbody interpolation is set to interpolate and collision detection set to continuous. Here's my player movement if this helps. Here is a sample of what it looks like, if you look at the background or the tilemap it's quite noticeable. https://youtu.be/h2rSheZWtKs
[SerializeField] private LayerMask groundLayerMask;
public float speed;
public float Jump;
public sword swordScript;
public GameObject swordSprite;
private float move;
private Rigidbody2D rb;
private BoxCollider2D boxCollider2d;
private bool facingRight;
public SpriteRenderer spr;
public Animator PlayerAnims;
public bool movementAllowed;
void Awake()
{
Application.targetFrameRate = 60;
Application.targetFrameRate = Screen.currentResolution.refreshRate;
boxCollider2d = GetComponent<BoxCollider2D>();
rb = GetComponent<Rigidbody2D>();
facingRight = true;
spr = GetComponent<SpriteRenderer>();
}
// Start is called before the first frame update
void Start()
{
boxCollider2d = GetComponent<BoxCollider2D>();
rb = GetComponent<Rigidbody2D>();
facingRight = true;
spr = GetComponent<SpriteRenderer>();
}
// Update is called once per frame
void FixedUpdate()
{
if(movementAllowed == true)
{
rb.velocity = new Vector2(move * speed, rb.velocity.y);
if (isGrounded() && Input.GetButtonDown("Jump"))
{
rb.AddForce(new Vector2(rb.velocity.x, Jump));
}
}
}
void Update()
{
move = Input.GetAxis("Horizontal");
rb.velocity = new Vector2(move * speed, rb.velocity.y);
if (movementAllowed == true)
{
Flip(move);
if (move == 0)
{
PlayerAnims.SetBool("isRunning", false);
}
else
{
PlayerAnims.SetBool("isRunning", true);
}
}
}
private bool isGrounded()
{
float extraHeightText = .1f;
RaycastHit2D raycasthit2d = Physics2D.BoxCast(boxCollider2d.bounds.center, boxCollider2d.bounds.size, 0f, Vector2.down, extraHeightText, groundLayerMask);
Color rayColour;
if (raycasthit2d.collider != null)
{
rayColour = Color.green;
PlayerAnims.SetBool("isJumping", false);
}
else
{
rayColour = Color.red;
PlayerAnims.SetBool("isJumping", true);
}
Debug.DrawRay(boxCollider2d.bounds.center + new Vector3(boxCollider2d.bounds.extents.x, 0), Vector2.down * (boxCollider2d.bounds.extents.y + extraHeightText), rayColour);
Debug.DrawRay(boxCollider2d.bounds.center - new Vector3(boxCollider2d.bounds.extents.x, 0), Vector2.down * (boxCollider2d.bounds.extents.y + extraHeightText), rayColour);
Debug.DrawRay(boxCollider2d.bounds.center - new Vector3(boxCollider2d.bounds.extents.x, boxCollider2d.bounds.extents.y + extraHeightText), Vector2.right * (boxCollider2d.bounds.extents.x), rayColour);
return raycasthit2d.collider != null;
}
private void Flip(float move)
{
if (move > 0 && !facingRight || move < 0 && facingRight)
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
if (swordScript.isFollowing == true)
{
Vector3 swordScale = swordSprite.transform.localScale;
swordScale.x *= -1;
swordSprite.transform.localScale = swordScale;
}
}
}
You are setting rb.velocity in both the Update() and FixedUpdate() methods. I would try only using one of those.
On top of that, your jump check also re-applies the X velocity along with the upward force. So if you're jumping the player will be pushed forward at double speed.
You also have an error being outputted in the console about an Index being out of range... I would look into that.
Can you also post your code for the parallax background?
FixedUpdate is a method where you want to do everything physics, player-controller and simulation related.
Update is just for rendering-related fluff i.e. code of no real consequence other than making things look correctly.
Hence:
Move all your player/physics controller code to FixedUpdate.
Move bg parallax code to Update.
Use Time.deltaTime (in Update) and Time.fixedDeltaTime (in FixedUpdate) time steps when animating or interpolating between values.
Ad #3.: Although - as #Menyus noted (below) - Time.deltaTime is all you really need.
Time.fixedDeltaTime is for that extra intent explicitness (but was necessary in earlier unity versions).
I don't want my player to jump in the air but I can't seem to find anything out.
This is what I have. They can jump, but they can jump forever and that's a problem.
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public float speed = 5f;
public float jumpSpeed = 8f;
private float movement = 0f;
public bool alive;
private Rigidbody2D rigidBody;
// Use this for initialization
void Start () {
rigidBody = GetComponent<Rigidbody2D> ();
// Use this for initialization
}
// Update is called once per frame
void Update () {
movement = Input.GetAxis ("Horizontal");
if (movement > 0f) {
rigidBody.velocity = new Vector2 (movement * speed, rigidBody.velocity.y);
}
else if (movement < 0f) {
rigidBody.velocity = new Vector2 (movement * speed, rigidBody.velocity.y);
}
else {
rigidBody.velocity = new Vector2 (0,rigidBody.velocity.y);
}
if(Input.GetButtonDown ("Jump")){
rigidBody.velocity = new Vector2(rigidBody.velocity.x,jumpSpeed);
}
}
}
An simple option is to maintain a boolean such as _inAir that gets set to true when the player first jumps, and to false when their RigidBody2D collides with the ground (see, e.g., OnCollisionEnter2D).
Then, the check if(Input.GetButtonDown ("Jump")){ becomes
if (!_inAir && Input.GetButtonDown("Jump")) {
So I have a 2d gameObject that behaves likes a spike trap that springs out of the ground when the character collides on the trigger. I use AddForce to the rigidbody 2D of the gameObject to manipulates its speed when coming out of the ground and I want it to just sticking out of the ground. How can I stop it when it reaches a certain tranform Y value.
Here is my code:
public float speed;
Rigidbody2D rb;
void Start () {
rb = GetComponent<Rigidbody2D>();
}
void Update () {
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "Player")
{
rb.AddForce(new Vector2(0, speed * Time.time), ForceMode2D.Impulse);
}
}
Certain transform value, or certain transform.position value?
I'll do it like this:
private float threshold = 10f;
private float startPosition = 0;
private RigidBody2D pikeRigidbody;:
private void Start()
{
startPosition = = this.transform.position;
pikeRigidbody = this.GetComponent<RigidBody2D>();
}
private void Update(){
if(this.transform.position.y >= (startPosition.y + threshold))
{
pikeRigidbody.velocity = Vector3.zero;
}
}
And attach the script to the pike object.
Edited to position.y instead of position
I am making a 2d top down game where the player can rotate the camera around himself as he moves through the world.
Everything works fine when the player is moving around the world the camera follows him fine. if he standing still then the camera rotation also works very well. However as soon as I start to do both then there is a jittery in the camera that makes all other objects jitter besides the player.
Now in working with this problem I have found out that this could have to do with the fact that I use rigidbody2d.AddRelativeForce (so physics) to move the player and that his movements are checked in FixedUpdate.
https://forum.unity3d.com/threads/camera-jitter-problem.115224/ http://answers.unity3d.com/questions/381317/camera-rotation-jitterness-lookat.html
I have tried moving my camera rotation and the following scripts to LateUpdate, FixedUpdate, Update you name it. Nothing seems to work. I am sure that there is some sort of delay between movement of the camera and the rotation that is causing this. I am wondering if anyone has any feedback?
I have tried disabling Vsync, does not remove it entirely
I have tried interpolating and extrapolating the rigidbody and although there is a difference it does not remove it entirely. Ironically it seemd if I have it set to none, it works best.
Scripts:
To Follow character, script applied to a gameobject that has the camera as a child
public class FollowPlayer : MonoBehaviour {
public Transform lookAt;
public Spawner spawner;
private Transform trans;
public float cameraRot = 3;
private bool smooth = false;
private float smoothSpeed = 30f;
private Vector3 offset = new Vector3(0, 0, -6.5f);
//test
public bool changeUpdate;
private void Start()
{
trans = GetComponent<Transform>();
}
private void FixedUpdate()
{
CameraRotation();
}
private void LateUpdate()
{
following();
}
public void following()
{
Vector3 desiredPosition = lookAt.transform.position + offset;
if (smooth)
{
transform.position = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
}
else
{
transform.position = desiredPosition;
}
}
void CameraRotation()
{
if (Input.GetKey("q"))
{
transform.Rotate(0, 0, cameraRot);
}
if (Input.GetKey("e"))
{
transform.Rotate(0, 0, -cameraRot);
}
}
public void SetTarget(string e)
{
lookAt = GameObject.Find(e).GetComponent<Transform>();
}
}
The character Controller, script applied to the Player, is called in FixedUpdate
private void HandleMovement()
{
if (Input.GetKey("w"))
{
rigid.AddRelativeForce(Vector2.up * speed);
}
if (Input.GetKey("s"))
{
rigid.AddRelativeForce(Vector2.down * speed);
}
if (Input.GetKey("a"))
{
if (facingRight)
{
Flip();
}
rigid.AddRelativeForce(Vector2.left * speed);
}
if (Input.GetKey("d"))
{
if (!facingRight)
{
Flip();
}
rigid.AddRelativeForce(new Vector2(1,0) * speed);
}
}
Try to use Coroutines. I modified some of my scripts to be more familiar to Your code, tried it, and I didn't see any jittery. I hope that will help You.
Camera Class:
public class CameraController : MonoBehaviour {
[SerializeField]
Transform CameraRotator, Player;
[SerializeField]
float rotationSpeed = 10f;
float rotation;
bool rotating = true;
void Start()
{
StartCoroutine(RotatingCamera());
}
IEnumerator RotatingCamera()
{
while (rotating)
{
rotation = Input.GetAxis("HorizontalRotation");
CameraRotator.Rotate(Vector3.up * Time.deltaTime * rotation * rotationSpeed);
CameraRotator.position = Player.position;
yield return new WaitForFixedUpdate();
}
}
private void OnDestroy()
{
StopAllCoroutines();
}
}
Player Class:
public class PlayerMovement : MonoBehaviour {
[SerializeField]
float movementSpeed = 500f;
Vector3 movementVector;
Vector3 forward;
Vector3 right;
[SerializeField]
Transform CameraRotator;
Rigidbody playerRigidbody;
float inputHorizontal, inputVertical;
void Awake()
{
playerRigidbody = GetComponent<Rigidbody>();
StartCoroutine(Moving());
}
IEnumerator Moving()
{
while (true)
{
inputHorizontal = Input.GetAxis("Horizontal");
inputVertical = Input.GetAxis("Vertical");
forward = CameraRotator.TransformDirection(Vector3.forward);
forward.y = 0;
forward = forward.normalized;
Vector3 right = new Vector3(forward.z, 0, -forward.x);
movementVector = inputHorizontal * right + inputVertical * forward;
movementVector = movementVector.normalized * movementSpeed * Time.deltaTime;
playerRigidbody.AddForce(movementVector);
yield return new WaitForFixedUpdate();
}
}
}
I fixed this problem finally:
First I made my cameraRotation() and follow() into 1 function and gave it a better clearer name:
public void UpdateCameraPosition()
{
if (Input.GetKey("q"))
{
transform.Rotate(0, 0, cameraRot);
}
else if (Input.GetKey("e"))
{
transform.Rotate(0, 0, -cameraRot);
}
Vector3 desiredPosition = lookAt.transform.position + offset;
transform.position = desiredPosition;
}
I then called that function from the character controller straight after the handling of movement. Both calls (handleMovement & cameraPosition) in fixedUpdate.
void FixedUpdate()
{
HandleMovement();
cameraController.UpdateCameraPosition();
}
and the jittering was gone.
So it seems it was imply because there was a slight delay between the two calls as the previous posts I read had said. But I had failed to be able to properly Set them close enough together.
Hope this helps someone.