- Home /
Adding an offset to instantiated object based on mouse distance from player
Hello, I've been trying to recreate a skill from the game Path of Exile in Unity, and I'm doing pretty well except one thing:
The skill shoots projectile(s), and if there is more than one projectile, the arc of the projectiles depend on how close of far your cursor to the player, if the cursor is close to player the angle between projectiles is very large, and projectiles get tighter if you aim away from the player.
Another question is how can I automate the offset of Instantiated projectiles based on the number Instantiated, like 45 degrees for 2 projectiles, 30 for 3, 20 for 4 etc. Thanks in advance!
Well, I think if you can get the distance of where the mouse and object are, then you can just math, algebra, to figure out the arc (maybe use pi)
Answer by Ogi_Magi · May 12, 2020 at 11:39 PM
I did it, here's the code with comments:
public int projCount;
public float projArcAngle = 100;
private float minAngle = 50;
private float maxAngle = 150;
void IceShot()
{
var playerPos = transform.position; // get the player position
Ray myRay = Camera.main.ScreenPointToRay(Input.mousePosition); // cast a ray in cursor's position
RaycastHit hitInfo;
Physics.Raycast(myRay, out hitInfo, 100);
Vector3 mousePos = new Vector3(hitInfo.point.x, transform.position.y, hitInfo.point.z); // exact position of mouse in world coordinates
var dist = Vector3.Distance(mousePos, playerPos); // distance between mouse position and player position
var finalArcAngle = projArcAngle;
if ((Mathf.Round(Mathf.Clamp(dist, 1, 20) / 2) > 5)) // distance is clamped between 1 and 20 then halved, so that 0 is player position and 10 is the max distance
{
var amount = ((Mathf.Round(Mathf.Clamp(dist, 1, 20) / 2) - 5) * 10); // amount is distance from middle to maximum multiplied by 10
finalArcAngle = projArcAngle - ((projArcAngle * amount) / 100); // we decrease the arc angle 10% per 1 distance from 5 to 10, so arrows will be tighter if aimed at a distance
finalArcAngle = Mathf.Clamp(finalArcAngle, minAngle, maxAngle); // finally clamp it to a desired value, in my case 50 to 150
}
var angle = (finalArcAngle / (projCount + 1)); // this is the offset angle each projectile will spawn, determined by amount of projectiles
for (int i = 1; i <= projCount; i++) // repeats until it reaches projCount
{
var calculatedAngle = (angle * i) - (finalArcAngle / 2); // finally, the exact position each arrow will spawn depending on i
Vector3 arrowRotation = new Vector3(arrowPos.transform.rotation.x, (arrowPos.transform.rotation.y + calculatedAngle), arrowPos.transform.rotation.z);
Instantiate(arrow, arrowPos.transform.position, arrowPos.transform.rotation * Quaternion.Euler(arrowRotation));
}
I know it's very messy and needs cleaning up, but i figured it all out by myself and kinda proud of it!
I fixed it, It now the only thing left is adjusting the angle based on the mouse distance from the player. Here's the code
public int projCount;
private float maxAngle = 120f;
void IceShot()
{
var angle = (maxAngle / (projCount + 1) );
for (int i = 1; i <= projCount; i++)
{
var offset = (angle * i) - (maxAngle / 2);
Vector3 offset3 = new Vector3(arrowPos.transform.rotation.x, (arrowPos.transform.rotation.y + offset), arrowPos.transform.rotation.z);
Instantiate(arrow, arrowPos.transform.position, arrowPos.transform.rotation * Quaternion.Euler(offset3));
}
}