Unity 2D instantiate prefabs order - unity3d

I'm instantiating enemy prefabs in waves, but when I do, the sprites are not consistent on the Z axis. Sometimes the second enemy is on top of the first one, and sometimes behind.
I want the new instance always behind the other.

Keep the instance position and instantiate the gameobject behind.
GameObject myGo1 = GameObject.Instantiate(prefabRef, Vector3.Zero,
Quaternion.Identity);
float distance = 1.0f;
Vector3 myGo2Pos = myGo1.position - myGo1.transform.forward * distance;
GameObject myGo2 = GameObject.Instantiate(prefabRef, myGo2Pos, Quaternion.Identity);
For the 1st GO instatiation, where Vector3.Zero you can choose the position of your choice. For whatever pos and rot you instantiate myGo1 with, the code Vector3 myGo2Pos = myGo1.position - myGo1.forward * distance; should instantiate the 2nd one distance meters behind.
Not debugged code, just for your inspiration.
Probably you might need the 2nd GO to look to the first one, in that case you can do:
GameObject myGo2 = GameObject.Instantiate(prefabRef, myGo2Pos, myGo1.transform.rotation);

Alright i figured it out. had to add a sprite renderer component like so:
SpriteRenderer spriteRenderer;
and where i instantiate:
void FollowPath()
{
if (!isAttacking)
{
if (waypointIndex < waypoints.Count)
{
**spriteRenderer = GetComponent<SpriteRenderer>();
spriteRenderer.sortingOrder++;**
Vector3 targetPosition = waypoints[waypointIndex].position;
float delta = waveconfig.GetMoveSpeed() * Time.deltaTime;
transform.position = Vector2.MoveTowards(transform.position, targetPosition, delta);
if (transform.position == targetPosition)
{
waypointIndex++;
}
}
}
}

Related

How can I make a 2D gun shoot towards the Direction of the mouse rather than the Position of the mouse?

Currently, my gun is able to instantiate new bullets that work fine (they have velocity and shoot towards the mouse's position). However, if the mouse is close to the player, I noticed the velocity is drastically lessened because it is targeting the mouse's position instead of the general direction.
Is there a way to get the angle from the player to the mouse, as well as apply velocity to the bullet, without it going exactly to the mouse's position?
public GameObject bullet;
public GameObject player;
// All the following is within an update function
//Gets the mouse position, and assigns direction from gun to mouse
Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 direction = mousePosition - transform.position;
float angle = Vector2.SignedAngle(Vector2.right, direction);
Vector2 PlayerDimensions = player.transform.lossyScale;
Vector2 PlayerLocation = player.transform.position;
//If the Gun weapon type is selected
if (weaponType == 2)
{
// Is used to flip the player sprite based on if the gun is facing left or right
if (PlayerLocation.x > mousePosition.x)
{
PlayerDimensions.x = -1;
player.transform.localScale = new Vector2(PlayerDimensions.x, PlayerDimensions.y);
}
else if (PlayerLocation.x < mousePosition.x)
{
PlayerDimensions.x = 1;
player.transform.localScale = new Vector2(PlayerDimensions.x, PlayerDimensions.y);
}
// Aims the gun based on if player is facing left or right
if (player.transform.lossyScale.x > 0)
{
transform.eulerAngles = new Vector3(0, 0, angle);
}
else if (player.transform.lossyScale.x < 0)
{
transform.eulerAngles = new Vector3(0, 0, 180 + angle);
}
}
if (Input.GetMouseButtonDown(0) && weaponType == 2)
{
Debug.Log("Shoot");
Vector3 myPos = new Vector3(transform.position.x, transform.position.y);
GameObject Bullet = Instantiate(bullet, myPos, Quaternion.identity);
Physics2D.IgnoreCollision(Bullet.GetComponent<BoxCollider2D>(), player.GetComponent<BoxCollider2D>(), GameObject.Find("blue_bullet_medium(Clone)"));
Bullet.GetComponent<Rigidbody2D>().velocity = new Vector2(direction.x, direction.y);
}
You can use normalized vector and speed instead of just direction to get constant bullet speed. In code it will be like this:
Vector2 direction = mousePosition - transform.position;
direction.Normalize();
Vector2 bulletVelocity = direction * _speed; // assume _speed can be tuned
The normalized vector will always have length 1, so the speed will not depend on the distance from the player to the cursor position

How can I move an object bullet towards a target?

I want to shoot a bullet prefab towards a target. I want it to just go towards the target current location. If the target changes position the bullets should still go to the old target position, instead of the current position the target is at.
Vector2 pos;
pos.x = tracker.transform.position.x;
pos.y = tracker.transform.position.y;
transform.position = Vector2.MoveTowards(transform.position, pos, bulletSpeed * Time.deltaTime);
The above code just makes the bullet prefab track the object even though the object moves. If an object is at 0,0 then the bullet should go towards it but if the player changes its position to 1,1 the bullet should still go to 0,0
Simply cache the previous position that the object was at and MoveTowards that instead of the player as that will go to the current position. Instead of continually updating the pos.x and pos.y, set them initially when the bullet is fired and not again.
private Vector2 targetPos;
private bool bulletInited = false;
private float bulletSpeed;
public void InitBulletTarget(Vector2 target)
{
bulletInited = true;
targetPos = target;
}
private void Update()
{
if(bulletInited)
{
transform.position = Vector2.MoveTowards(transform.position, targetPos, bulletSpeed * Time.deltaTime);
}
}
When you Instantiate your bullet prefab, you will want to call the InitBulletPosition and send in the proper position which would be the tracker.transform.position.
An example would be
private void SpawnBullet()
{
// spawn the two bullets
YourBulletScript bullet1 = Instantiate(bullet, firePoint.position, firePoint.rotation).GetComponent<YourBulletScript>();
YourBulletScript bullet2 = Instantiate(bullet, firePoint2.position, firePoint2.rotation).GetComponent<YourBulletScript>();
// set their target position to move towards
bullet1.InitBulletTarget(tracker.transform.position);
bullet2.InitBulletTarget(tracker.transform.position);
}

Unity Mouse Input without Ray/Raycast and Colliders

First of all thank you for your time. I'm quite new in this so I'm struggling a bit. I'm trying to make a drag and release shooter which doesn't really depend on colliders or raycasts but solely depends on mouse delta and camera position. The way I'm trying to have it done is I'm mapping mouse position (x,y) to velocity direction such as new Vector3(mouseX, 0f, mouseY) then rotating it about Y axis to match the visual drag on the screen.
void OnMouseUp()
{
releasePos = Input.mousePosition;
Vector2 m_direction = releasePos - initialPos;
Vector3 direction = new Vector3(m_direction.x, 0, m_direction.y);
float userDrag = Mathf.Clamp(direction.magnitude, 0f, maxVelocity);
direction = Translation(direction);
direction = Vector3.Normalize(direction);
rigidbody.velocity = (direction * userDrag) * force;
}
private Vector3 Translation(Vector3 direction)
{
Vector3 camPos = Camera.main.transform.position;
camPos.y = 0;
float angle = Vector3.Angle(new Vector3(0f, 0f, 1f), camPos);
Quaternion translatedAngle = Quaternion.AngleAxis(angle, Vector3.up);
direction = translatedAngle * direction;
But as the angle changes it kinda fails to deliver what I'm asking for. Is there a way I can avoid bunch of if, else statements for the angle value or a shorter way of doing this?
Example
OnMouseUp is fundamentally a collider method.
Meaning, the mouse MUST be over the GameObject's collider for the GameObject this code is attached to. If you want to move away from using colliders, then you need to move away from this method.
The generic works-anywhere way of saying "is the mouse button up or down?" is the static methods available in the Input class:
Input.GetMouseButtonDown() True on the single frame after the mouse button is depressed
Input.GetMouseButtonUp() True on the single frame after the mouse button is released
Input.GetMouseButton() True any frame the mouse button is depressed (otherwise false)
So I think I have a solution finally and I thought I'd share it for people who might be interested.
The challenge was to rotate mouse delta's direction according to camera position so it gives a natural vibe to the player when dragging and releasing the ball for putting. I did some tests to see where my code had problems rotating delta direction properly(so it matches the screen) and realized when I'm "looking from" (0,0,1) for comparison while the camera's x position is positive it works fine. But when x is negative it doesn't because Vector3.Angle doesn't return a negative value as far as I'm concerned so I just multiplied the result with minus. Seems to work.
Here is the final code:
private void Start()
{
rigidbody = GetComponent<Rigidbody>();
}
void OnMouseDown()
{
ballPos = Input.mousePosition;
}
void OnMouseUp()
{
Vector2 m_direction = Input.mousePosition - ballPos;
Vector3 direction = new Vector3(m_direction.x, 0, m_direction.y);
float userDrag = Mathf.Clamp(direction.magnitude, 0f, maxVelocity);
direction = Translation(direction);
direction = Vector3.Normalize(direction);
rigidbody.velocity = (direction * userDrag) * force;
}
private Vector3 Translation(Vector3 direction)
{
float angle = GetAngle();
Quaternion translatedAngle = Quaternion.AngleAxis(angle, Vector3.up);
direction = translatedAngle * direction;
return direction;
}
private float GetAngle()
{
Vector3 camPos = Camera.main.transform.position;
camPos.y = 0;
if (camPos.x > 0)
{
angle = Vector3.Angle(Vector3.forward, camPos);
}
else if (camPos.x <0)
{ angle = -Vector3.Angle(Vector3.forward, camPos); }
return angle;
}
please do share if you have suggestions regarding the code.

Box Collider 2D overlapping in Unity

I have two GameObjects with a box collider. One is the player, moved with a fixed velocity towards the other. The collision stops the player (the Poo character ;D)
But they overlap, you can see it here:
I don't know why this is happening. Colliding with the top or bottom works just fine...The same effect happens from the left side. The green block has just a collider, no RigidBody.
Gif:
Another Gif, with MovePosition() ... Colliding fromt the top works, but "reentering" stops the character. Why?!:
GIF, moving up and down is okay, left and right at the top of the blocks slows him down. Weird...
Movement Script:
public class PlayerController : MonoBehaviour
{
public float Speed = 10f;
private Rigidbody2D rb2D;
private Vector2 DirectionLeft;
private Vector2 DirectionRight;
private Vector2 DirectionUp;
private Vector2 DirectionDown;
private Vector2 CurrentDirection;
// Use this for initialization
void Start()
{
rb2D = GetComponent<Rigidbody2D>();
DirectionLeft = new Vector2(Speed*-1, 0);
DirectionRight = new Vector2(Speed, 0);
DirectionUp = new Vector2(0, Speed * -1);
DirectionDown = new Vector2(0, Speed);
CurrentDirection = DirectionLeft;
}
void SetAnimationDirection()
{
Vector3 scale = transform.localScale;
if (CurrentDirection == DirectionLeft)
scale.x = 1;
else
scale.x = -1;
transform.localScale = scale;
}
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal");
float moveVertical = Input.GetAxis("Vertical");
if (moveHorizontal > 0)
CurrentDirection = DirectionRight;
if (moveHorizontal < 0)
CurrentDirection = DirectionLeft;
if (moveVertical < 0)
CurrentDirection = DirectionUp;
if (moveVertical > 0)
CurrentDirection = DirectionDown;
Debug.Log(CurrentDirection);
SetAnimationDirection();
rb2D.velocity = CurrentDirection;
}
The solution to the first problem (overlapping):
I used transform.localScale = scale to change the direction of the sprite on every FixedUpdate() and also forgot to update the factor of the scale, since I added a new extension, which resized my object by 1 more Unity unit.
The other problem (getting stuck at the edge) is solved adding setting the Edge Radius of the Collider 2D to something below 1.0f (e.g 0.09f) and also resize the bounding box. This will prevent the object from getting stuck at the edges, because the bounding box edges are now rounded.

Updated position Unity3d

I have a bullet that has to hit a constantly moving enemy.
So, in BulletScript, I have declared a Transform
public Transform enemy; //and assigned enemy object to it that is continuously moving and changing its position
Now, when I try to use enemy.position in bullet script so as to hit it, enemy.positiongives the position at which the enemy strted and not the position at which it was when bulletprefab was shot.
How can I get the updated position of enemy object every time bulletprefab is instantiated.
This is how I am changing the enemy's position:
void Update () {
float amttomove = currentSpeed * Time.deltaTime;
transform.Translate (Vector3.left * amttomove);
if (transform.position.x < 0f)
setposandspeed();
}
void setposandspeed()
{
x = 11.5f;
z = 0.0f;
currentSpeed = Random.Range (MinSpeed, MaxSpeed);
y = Random.Range (0f, 2.5f);
transform.position = new Vector3(x, y, z);
}
This is where tried to use enemy's position in bulletscript:
float target_Distance = Vector3.Distance(Projectile.position, Target.transform.position );
It is called inside Start() of bulletscript
This is where I instantiated the bullet in Player class:
Inside Updated method:
if (Input.GetKeyDown ("space")) {
Vector3 position = new Vector3 (transform.position.x, transform.position.y + collider.bounds.size.y / 2);
Instantiate (bulletprefab, position, Quaternion.identity);
}
enemy.position in bullet script so as to hit it, enemy.positiongives
the position at which the enemy strted and not the position at which
it was when bulletprefab was shot.
No, enemy.position will return the current position of the enemy, suitable if you want your projectile follow the enemy.
If you are instantiating dynamically your projectiles (BullerScript) and want to shoot them toward the position the enemy is during the shoot frame, record it just after bullet is instantiated for example:
class BulletScript : MonoBehavior
{
public Vector3 targetPos;
void Update()
{
//move toward targetPos
}
}
BulletScript bullet = GameObject.Instantiate(bulletPrefab,shootPosition) as BulletScript;
bullet.targetPos = enemyPosition;