Keeping the CircleCollider2D aligned with the sprite Unity - c#

I am making a 2D plant simulation using 2D Sprites in Unity. The plants are represented as circular sprites. What I want to do is to increase the radius of the sprite and have the CircleCollider2D follow along. Since they have different scalings I am using a procuental increase of the radius instead of an absolute increase. But the problem is that the collider radius increases faster than the sprite, even though the relation between the collider radius and the sprite radius stays the same.
Here is the code which increases the size:
void Grow(GameObject plant)
{
float currentRadius = plant.GetComponent<CircleCollider2D>().radius; //Radius of the collider
float scaledRadius = Mathf.Max(plant.transform.localScale.x, transform.localScale.y); //Radius of the sprite
float radiusIncrease = growthSpeed * Time.deltaTime;
float procIncrease = (currentRadius + radiusIncrease) / currentRadius; //The procuental increase of the radius, need for sprite scaling
plant.GetComponent<CircleCollider2D>().radius *= procIncrease;
Vector3 oldLocalScale = plant.transform.localScale;
Vector3 newLocalScale = new Vector3(oldLocalScale.x * procIncrease, oldLocalScale.y * procIncrease, oldLocalScale.z);
plant.transform.localScale = newLocalScale;
}

I found out that the radius of the CircleCollider2D increases with the sprite, which means that I don't have to change the radius of the collider myself.

Related

How do I get a bullet prefab's sprite to use the same rotation as my weapon?

I'm working on a top down concept where the gun revolves around the player and flips according to the side your crosshair is on (similar to ZERO Sievert). I'm trying to have my bullet sprite have the correct rotation when firing in relation to my players weapon.
Below is how I'm instantiating the bullet in a shooting script which fires the correct way but the sprite itself is not rotated correctly.
void Shoot()
{
GameObject bullet = Instantiate(bulletPrefab, firingPoint.position, firingPoint.rotation);
Rigidbody2D rb = bullet.GetComponent<Rigidbody2D>();
rb.AddForce(firingPoint.right * bulletForce, ForceMode2D.Impulse);
}
and in my weapon handling script this is my implementation of the weapon rotation, I am flipping the weapons y scale to correct the sprite for now.
private void FixedUpdate()
{
RotateWeapon();
if (crosshair.transform.position.x < 0)
{
FlipWeapon();
}
}
void RotateWeapon()
{
float AngleRad = Mathf.Atan2(crosshair.transform.position.y - currentWeapon.transform.position.y, crosshair.transform.position.x - currentWeapon.transform.position.x);
float AngleDeg = (180 / Mathf.PI) * AngleRad;
currentWeapon.transform.rotation = Quaternion.Euler(0, 0, AngleDeg);
}
void FlipWeapon()
{
currentScale = transform.parent.localScale;
currentScale.y *= -1;
currentWeapon.transform.localScale = currentScale;
}
I'm currently at a standstill on how to achieve this as most resources I've come across for top down shooting have the player turning up to a full 360 degrees where my player only faces left or right and the weapon itself only has a range of motion of 180 degrees on either side before its set to flip.
Maybe you can try and add an offset so when you Instantiate the bullet it will look something like this:
GameObject bullet = Instantiate(bulletPrefab, firingPoint.position, firingPoint.rotation + offset);
here offset will be a rotational x y z coordinate so you would want to rotate it on the z coordinate (try all of them until you fin the right one) and rotate it either -90 degrees or 90 deegrees. You might have to rotate it 180 degress but dont use 270 instead use -90. Trust me it will help in your later days in coding. Also make sure to set offset as a variable:
private Vector3 offset = 0, 0, -90;
!Remember you can change the x y z coordinates!

Spawn within field of view but always below a certain height

I have two systems that spawn flying enemies. The first system spawns enemies within the FOV:
distanceFromPlayer = 20;
Ray ray = Camera.main.ScreenPointToRay(new Vector3(UnityEngine.Random.Range((float)leftRange,(float)rightRange), UnityEngine.Random.Range((float)bottomRange,(float)topRange), 0));
screenPosition = ray.GetPoint (distanceFromPlayer);
The second system spawns them randomly but with a max angle between enemy and ground. Look at it as if there was a half sphere with the player as center that has been topped off: the enemy can spawn on the surface of that topped sphere:
float distance = distanceFromPlayer;
float yaw = UnityEngine.Random.Range(0,360);
float pitch = UnityEngine.Random.Range(1,35);
screenPosition = RotationHelper.ConvertYawPitch (Vector3.forward * distance, yaw, pitch);
and
public static class RotationHelper {
public static Vector3 ConvertYawPitch(Vector3 vector, float yaw, float pitch)
{
Quaternion yawRotation = Quaternion.AngleAxis (yaw, Vector3.up);
Vector3 yawedZAxis = yawRotation * Vector3.left;
Quaternion pitchRotation = Quaternion.AngleAxis (pitch, yawedZAxis);
Vector3 yawedVector = yawRotation * vector;
Vector3 position = pitchRotation * yawedVector;
return position;
}
}
Now, I want to have a third system for another type of enemies, which basically combines the two systems. So: I want them to spawn inside the field of view, but not above a certain hight, measured from the ground (or below a certain angle like in system two). So if you look to the sky, it should spawn the enemies below the camera's field of view.
I've tried an approach where I make a dummy camera that moves along with the real camera, but can't look upside, but I have the feeling it affects my performance quite drastically, and it doesn't feel like the most efficient way to do it.
Any help is much appreciated!
I went for an approach where I put an invisible ceiling above the player that follows the player's position. If an enemy would spawn behind this invisible ceiling, I recalculate the spawn point.
I use the same technique to make sure enemies don't spawn beneath the floor or behind objects.
This is probably not the most performance friendly way because chances are quite high that it needs to recalculate, so feel free to share other approaches.

How can I move some object in circle around another object?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TargetBehaviour : MonoBehaviour
{
// Add this script to Cube(2)
[Header("Add your turret")]
public GameObject Turret;//to get the position in worldspace to which this gameObject will rotate around.
[Header("The axis by which it will rotate around")]
public Vector3 axis;//by which axis it will rotate. x,y or z.
[Header("Angle covered per update")]
public float angle; //or the speed of rotation.
public float upperLimit, lowerLimit, delay;// upperLimit & lowerLimit: heighest & lowest height;
private float height, prevHeight, time;//height:height it is trying to reach(randomly generated); prevHeight:stores last value of height;delay in radomness;
// Update is called once per frame
void Update()
{
//Gets the position of your 'Turret' and rotates this gameObject around it by the 'axis' provided at speed 'angle' in degrees per update
transform.RotateAround(Turret.transform.position, axis, angle);
time += Time.deltaTime;
//Sets value of 'height' randomly within 'upperLimit' & 'lowerLimit' after delay
if (time > delay)
{
prevHeight = height;
height = Random.Range(lowerLimit, upperLimit);
time = 0;
}
//Mathf.Lerp changes height from 'prevHeight' to 'height' gradually (smooth transition)
transform.position = new Vector3(transform.position.x, Mathf.Lerp(prevHeight, height, time), transform.position.z);
}
}
In general it's working the problem is for example if I set the axis x,y,z to 1,1,1 on the variable: axis
And Angle set to 1 Upper limit to 50 Lower limit to 2 and delay to 2.
Then the object is making a circle around the other object but sometimes when the object is getting higher the most he get higher the object making a bigger circle and then when the object is getting lower the circle is smaller.
How can I make it to keep the circle radius static ?
The main goal is to move the object in circles around another object in random highs limits for example 2 and 50 but I want to keep the same radius all the time. Now the radius is changing by depending on the height.
As you are constantly moving the object upwards, if you want the radius of rotation to remain constant then the axis of rotation must veertical ie - Vector3.up or new Vector3(0, 1, 0)

Unity - Sprite Rotation + Get Angle

Im trying to get a sprite rotation by key input (arrow down or up).
The point is lifting the arrow (sprite) to choose the angle. Its like a system of a golf game, actually.
So far i tried:
void Update () {
if (Input.GetKey(KeyCode.UpArrow)){
transform.Rotate (Vector3.forward * -2); }
if (Input.GetKey(KeyCode.DownArrow)){
transform.Rotate (Vector3.forward * +2); }
}
I will need the angle, since it will be related to a "shot" part i will be doing next. My point is setting the right angle with the keys up and down.
I can move the "arrow" sprite with my code, but i cannot set the max angle (90), minimum (0) and get the angle to use in the shot ^^
Hard question to answer without just simply giving you the code. This code works by assuming your character's forward vector is actually it's right vector (common in 2d sprite games) in order to shoot in the other direction, rotate your objects y axis 180.
float minRotation = 0f;
float maxRotation = 90f;
float rotationSpeed = 40f; //degrees per second
//get current rotation, seeing as you're making a sprite game
// i'm assuming camera facing forward along positive z axis
Vector3 currentEuler = transform.rotation.eulerAngles;
float rotation = currentEuler.z;
//increment rotation via inputs
if (Input.GetKey(KeyCode.UpArrow)){
rotation += rotationSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.DownArrow)){
rotation -= rotationSpeed * Time.deltaTime;
}
//clamp rotation to your min/max
rotation = Mathf.Clamp(rotation, minRotation, maxRotation );
//set rotation back onto transform
transform.rotation = Quaternion.Euler( new Vector3(currentEuler.x, currentEuler.y, rotation));
If you were making a golf game, you'd set the ball's velocity to be transform.right * shotPower

TransformDirection not behaving as expected when creating RTS camera

I'm trying to create a RTS game from scratch using Unity engine. I started with this Unity RTS game tutorial and I'm setting up the camera. Basically what I do is, that I generate [x,0,z] vector for movement. I then need to apply it on camera.
It works perfectly if the camera isn't rotated - but it usually IS rotated and must be rotatable.
According to the tutorial and the docs, I can transform vector to camera's point of view using Camera.main.transform.TransformDirection(MyVector). Which is what I do:
//Get mouse position
float xpos = Input.mousePosition.x;
float ypos = Input.mousePosition.y;
//Create vector for movement
Vector3 movement = new Vector3(0, 0, 0);
//horizontal camera movement
if (xpos >= 0 && xpos < ResourceManager.ScrollWidth)
{
movement.x -= ResourceManager.ScrollSpeed;
}
else if (xpos <= Screen.width && xpos > Screen.width - ResourceManager.ScrollWidth)
{
movement.x += ResourceManager.ScrollSpeed;
}
//vertical camera movement
if (ypos >= 0 && ypos < ResourceManager.ScrollWidth)
{
movement.z -= ResourceManager.ScrollSpeed;
}
else if (ypos <= Screen.height && ypos > (Screen.height - ResourceManager.ScrollWidth))
{
movement.z += ResourceManager.ScrollSpeed;
}
//make sure movement is in the direction the camera is pointing
//but ignore the vertical tilt of the camera to get sensible scrolling
movement = Camera.main.transform.TransformDirection(movement);
//Up/down movement will be calculated diferently
movement.y = 0;
However, if I do this, the vertical movement doesn't work for the inital camera rotation, and when I rotate camera, the movement happens at strange speeds.
How can I properly apply the movement vector on camera?
Well, the problem here is that TransformDirection will preserve the lenth of the vector. So if you tilt the camera downwards the overall length get distributed between the y, x and z axis. Since you simply eliminate the y part the vector will get shorter. The more the camera is tilted the more you will lose on the other two axes.
It's usually easier to just rotate a unit vector, modify it as you want and normalize it when done. This unit vector can then be scaled by your actual movement vector. Something like that:
// [...]
Vector3 forward = Camera.main.transform.forward;
Vector3 right = Camera.main.transform.right;
forward.y = 0f;
right.y = 0f; // not needed unless your camera is also rotated around z
movement = forward.normalized * movement.z + right.normalized * movement.x;
// [...]
Another approach is to seperate your two rotations. So by using an empty GameObject that is only rotated around y and have the camera a child of that gameobject. Now the camera will only be rotated around the local x axis to tilt it the way you want. To lat the camera look into a different direction you rotate the empty GameObject around y. That way you can use the transform of the empty GameObject to transform the direction just the way you did in your code since the tilt of the camera doesn't matter.

Categories

Resources