14t*_*nch 6 c# angle unity-game-engine
I have a 2d arrow rotating to always face the a target (the target in this case is the cursor), the pivot is my player character. I need to restrict this arrow to only follow the target if it is inside an angle of the player, an example would be 90 degrees, so it would only follow if the cursor is in the top right part of the screen.
I have worked with vector directions and methods such as Vector2D.angle, but they all seem to have some restriction i can't workaround, Vector2D.angles restriction is that the 3rd position it uses to calculate the angle is the world center(0, 0), my player is mobile so that doesn't work. So i think what im asking is if theres a way to store an angle, and then check if something is within that.
Here is the code i use for rotating my arrow, theres more to the script but i removed the unnecesary parts:
public float speed;
public Transform target;
void Update()
{
Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 direction = target.position - transform.position;
target.position = mousePosition;
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
Quaternion rotation = Quaternion.AngleAxis(angle, Vector3.forward);
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, speed * Time.deltaTime);
Run Code Online (Sandbox Code Playgroud)
Sorry if this is formatted poorly, its my first time posting here, thank you a million times if you are able to help me, i have been stuck on this for days.
Was asked to clarify question so here is an attempt:
This picture shows an example of what i mean, the arrow is rotating around the center of the circle, (it is rotating so it always points towards my cursor). What i need is a way to restrict it so it only points towards the cursor if it is within a specific angle (red lines in picture), that's what im having trouble with. I can't find a way to store this threshold and i can't seem to find a way to compare the cursors direction with it.
I think it would be possible if it was possible to choose a custom center for Vector2D.angle, but that doesn't seem to be the case.
I hope this clarifies what my question, i may just very well be stupid and overlooking something obvious but i really can't find a way to make this possible. thanks again.
首先,我们需要知道世界空间中的边界方向:
public Vector2 boundaryDirectionLeft;
public Vector2 boundaryDirectionRight;
Run Code Online (Sandbox Code Playgroud)
boundaryDirectionLeft
重要的是,从到顺时针形成的角度boundaryDirectionRight
是箭头应保留在内部的区域。就您的图像而言,boundaryDirectionLeft
可能是Vector2.up
并且boundaryDirectionRight
可能是类似的东西new Vector2(1f,-1f)
。
在应用任何旋转之前,我们还需要知道箭头面向哪个局部方向。例如,如果箭头始终指向局部红色箭头轴(局部右方向),则这将是Vector2.right
:
public Vector2 localArrowDirection;
Run Code Online (Sandbox Code Playgroud)
最后,我们需要一个最高旋转速度,这样我们在旋转时就不会扭曲箭头。一个好的开始值可能是360f
每秒 360 度。尝试尝试不同的值以找到您喜欢的值:
public float maxRotationSpeed;
Run Code Online (Sandbox Code Playgroud)
在 中Update
,确定到目标的方向:
Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 direction = mousePosition - transform.position;
Run Code Online (Sandbox Code Playgroud)
然后,我们需要知道箭头当前指向哪里。我们可以用它Transform.TransformVector
来查找本地localArrowDirection
在世界空间中指向的位置:
Vector2 currentDirection = transform.TransformVector(localArrowDirection);
Run Code Online (Sandbox Code Playgroud)
然后,确定from到目标方向的带符号角度boundaryDirectionLeft
,同样 fromboundaryDirectionLeft
到boundaryDirectionRight
,以及同样 fromboundaryDirectionLeft
到当前面向方向:
float directionAngle = Vector2.SignedAngle(boundaryDirectionLeft, direction);
float boundaryAngle = Vector2.SignedAngle(boundaryDirectionLeft, boundaryDirectionRight);
float currentAngle = Vector2.SignedAngle(boundaryDirectionLeft, currentDirection);
Run Code Online (Sandbox Code Playgroud)
这些值的范围为 [-180,180],但我们希望它们在 [0,360) 范围内表示,以便以后的数学计算更容易,因此我们可以对该总和进行添加360f
和使用:Mathf.Repeat
directionAngle = Mathf.Repeat(directionAngle+360f, 360f);
boundaryAngle = Mathf.Repeat(boundaryAngle+360f, 360f);
currentAngle = Mathf.Repeat(currentAngle+360f, 360f);
Run Code Online (Sandbox Code Playgroud)
此时,距离该点directionAngle
顺时针旋转多少度, 和是多少度, 和我们当前面向的方向相同。boundaryDirectionLeft
target
boundaryAngle
boundaryDirectionRight
currentAngle
所以,现在,我们需要知道如何正确地将角度限制boundaryAngle
在 0 和 之间。任何上方太远的东西boundaryAngle
实际上都更接近左边界,并且应该被夹紧到左边界。事实上,由于一切都在 0 到 360 之间,所以高于的值都更boundaryAngle+(360f-boundaryAngle)/2f
接近左侧。因此,我们只需将高于该值的值设置为 0 度boundaryDirectionLeft
:
if (directionAngle > boundaryAngle + (360f - boundaryAngle)/2f)
{
directionAngle = 0f;
}
Run Code Online (Sandbox Code Playgroud)
所以,现在我们可以用 的directionAngle
高位钳位boundaryAngle
(它已经在 的底部钳位0f
,所以我们可以Mathf.Min
在这里使用):
directionAngle = Mathf.Min(directionAngle, boundaryAngle);
Run Code Online (Sandbox Code Playgroud)
现在我们可以使用我们的 来限制directionAngle
和之间的角度差异:currentAngle
maxRotationSpeed
float deltaAngle = Mathf.Clamp(directionAngle-currentAngle,
-maxRotationSpeed * Time.deltaTime,
maxRotationSpeed * Time.deltaTime);
Run Code Online (Sandbox Code Playgroud)
现在我们可以顺时针旋转变换deltaAngle
度数(在世界空间中):
transform.Rotate(0f,0f,deltaAngle,Space.World);
Run Code Online (Sandbox Code Playgroud)