Hello ,I am Edwin
首先谢谢大家的支持,其次如果你碰到什么其他问题的话,欢迎来 我自己的一个 讨论群559666429
来,大家一起找答案,共同进步
由于逻辑比较简单,所以直接代码吧。功能主要是 :
注意: 使用这个功能的时候 摄像机的 旋转 必须 都为 0。负责要么,你要稍微调节代码,要不就没有办法使用
1. 获得 A相对与B所在的位置。直接 得出,是在B的 左边,右边,还是上边,亦或者 下边。 针对读者是 Unity 基础者。顺路造福一下人类,高手绕路。
2. 制作像 UGUI Anchor Presets 一样效果的 ,让子类对象去 父类对象的 左边,右边,左上角,右上角,左下角…..
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Azimuth
{
Zero,
UpperLeft,
UpperRight,
LowerRight,
LowerLeft,
Left,
Right,
Up,
Down,
}
public class JudgmentDirection : MonoBehaviour {
public GameObject other;
float dot ;
float dot_angle;
Vector3 cross;
bool isZheng = false;
bool isShun = false;
public Azimuth m_Azimuth;
Azimuth fangwei ;
private void FixedUpdate()
{
if(other)
{
fangwei = GetAzimuth(other.transform);
}
}
Azimuth GetAzimuth(Transform other)
{
Vector3 dic = other.transform.position - transform.position;
dot = Vector3.Dot(dic.normalized, transform.up);
dot_angle = Mathf.Acos(dot) * Mathf.Rad2Deg;
isZheng = (Mathf.Sign(dot) == -1) ? false : true;
cross = Vector3.Cross(dic.normalized, transform.up);
isShun = (cross.z >= 0) ? true : false;
float maxValue = Mathf.Cos(45.0f * Mathf.Deg2Rad);
Debug.Log(maxValue);
if (Mathf.Abs(dot) > maxValue)
{
if (isZheng)
{
return Azimuth.Up;
}
else
{
return Azimuth.Down;
}
}
else
{
if (isShun)
{
return Azimuth.Right;
}
else
{
return Azimuth.Left;
}
}
Debug.DrawLine(transform.position, transform.position + cross.normalized * 2, Color.yellow);
Debug.DrawLine(transform.position, transform.position + dic.normalized * 2, Color.blue);
Debug.DrawLine(transform.position, transform.position + transform.up * 2, Color.green);
}
void ChangeAzimuth(Azimuth azimuth)
{
Vector2 b = new Vector2(other.transform.localScale.x, other.transform.localScale.z);
Vector2 offset = new Vector2((other.transform.localScale.x / (1 / b.x) * 2), (other.transform.localScale.z / (1 / b.y) * 2));
Vector2 added = new Vector2(Mathf.Pow((1 / b.x) / 2, 2), Mathf.Pow((1 / b.y) / 2, 2));
Debug.Log(added);
Vector3 newPos = Vector3.zero;
switch (azimuth)
{
case Azimuth.UpperLeft:
newPos = new Vector3(-offset.x * added.x + other.transform.localScale.x / 2, offset.y * added.y - other.transform.localScale.z / 2, other.transform.localPosition.z);
break;
case Azimuth.UpperRight:
newPos = new Vector3(offset.x * added.x - other.transform.localScale.x / 2, offset.y * added.y - other.transform.localScale.z / 2, other.transform.localPosition.z);
break;
case Azimuth.LowerLeft:
newPos = new Vector3(-offset.x * added.x + other.transform.localScale.x / 2, -offset.y * added.y + other.transform.localScale.z / 2, other.transform.localPosition.z);
break;
case Azimuth.LowerRight:
newPos = new Vector3(offset.x * added.x - other.transform.localScale.x / 2, -offset.y * added.y + other.transform.localScale.z / 2, other.transform.localPosition.z);
break;
case Azimuth.Left:
newPos = new Vector3(-offset.x * added.x + other.transform.localScale.x / 2, 0 , other.transform.localPosition.z);
break;
case Azimuth.Right:
newPos = new Vector3(offset.x * added.x - other.transform.localScale.x / 2, 0 , other.transform.localPosition.z);
break;
case Azimuth.Up:
newPos = new Vector3(0 , offset.y * added.y - other.transform.localScale.z / 2, other.transform.localPosition.z);
break;
case Azimuth.Down:
newPos = new Vector3(0 , -offset.y * added.y + other.transform.localScale.z / 2, other.transform.localPosition.z);
break;
default:
break;
}
other.transform.localPosition = newPos;
}
int index = (int)Azimuth.UpperLeft;
void OnGUI()
{
GUIStyle style = new GUIStyle();
style.fontSize = 40;
style.normal.textColor = Color.white;
GUIStyle style2 = new GUIStyle();
style2.fontSize = 20;
style2.normal.textColor = Color.white;
style2.border = new RectOffset(3,3,2,2);
GUI.Label(new Rect(30, 10, 100, 200), dot.ToString(), style);
GUI.Label(new Rect(30, 50, 100, 200), dot_angle.ToString(), style);
GUI.Label(new Rect(30, 100, 100, 200), cross.ToString(), style);
GUI.Label(new Rect(30, 300, 100, 200), fangwei.ToString(), style);
GUI.skin.button.fontSize = 30;
GUI.skin.button.fixedWidth = 250f;
GUI.skin.button.fixedHeight = 100f;
bool isClick = GUI.Button(new Rect(30, 400, 100, 200), m_Azimuth.ToString());
if(isClick)
{
if(index > (int)Azimuth.Down)
{
index = (int)Azimuth.UpperLeft;
}
m_Azimuth = (Azimuth)index;
ChangeAzimuth(m_Azimuth);
index++;
Debug.Log(m_Azimuth.ToString());
}
}
}
因为摄像机的角度而做相应的变化这块还没有做。所以目前上面的功能只支持 “Inspector”面板中 Rotation 为 (0,0,0)的摄像机。
因为自己项目原因相机 Rotation 成 (90,0,0)。所以代码做了改变,如下面所展示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class JudgmentDirection : MonoBehaviour
{
public GameObject other;
float dot;
float dot_angle;
Vector3 cross;
bool isZheng = false;
bool isShun = false;
public Azimuth m_Azimuth;
Azimuth fangwei;
private void Update()
{
if (other)
{
fangwei = GetAzimuth(other.transform);
}
}
Azimuth GetAzimuth(Transform other)
{
Vector3 dic = other.transform.position - transform.position;
dot = Vector3.Dot(dic.normalized, transform.forward.normalized);
dot_angle = Mathf.Acos(dot) * Mathf.Rad2Deg;
isZheng = (Mathf.Sign(dot) == -1) ? false : true;
cross = Vector3.Cross(dic.normalized, transform.forward.normalized);
isShun = (cross.y >= 0) ? true : false;
float maxValue = Mathf.Cos(45.0f * Mathf.Deg2Rad);
Debug.Log(maxValue);
Debug.DrawLine(transform.position, transform.position + cross.normalized * 20, Color.yellow);
Debug.DrawLine(transform.position, transform.position + dic.normalized * 20, Color.blue);
Debug.DrawLine(transform.position, transform.position + transform.forward.normalized * 20, Color.green);
if (Mathf.Abs(dot) > maxValue)
{
if (isZheng)
{
return Azimuth.Up;
}
else
{
return Azimuth.Down;
}
}
else
{
if (isShun)
{
return Azimuth.Left;
}
else
{
return Azimuth.Right;
}
}
}
void ChangeAzimuth(Azimuth azimuth)
{
Vector2 b = new Vector2(other.transform.localScale.x, other.transform.localScale.z);
Vector2 offset = new Vector2((other.transform.localScale.x / (1 / b.x) * 2), (other.transform.localScale.z / (1 / b.y) * 2));
Vector2 added = new Vector2(Mathf.Pow((1 / b.x) / 2, 2), Mathf.Pow((1 / b.y) / 2, 2));
Debug.Log(added);
Vector3 newPos = Vector3.zero;
Vector3 otherScale = other.transform.localScale;
float fixedAixs = other.transform.localPosition.y;
switch (azimuth)
{
case Azimuth.UpperLeft:
newPos = new Vector3(-offset.x * added.x + otherScale.x / 2, fixedAixs, offset.y * added.y - otherScale.z / 2);
break;
case Azimuth.UpperRight:
newPos = new Vector3(offset.x * added.x - otherScale.x / 2, fixedAixs, offset.y * added.y - otherScale.z / 2);
break;
case Azimuth.LowerLeft:
newPos = new Vector3(-offset.x * added.x + otherScale.x / 2, fixedAixs, -offset.y * added.y + otherScale.z / 2);
break;
case Azimuth.LowerRight:
newPos = new Vector3(offset.x * added.x - otherScale.x / 2, fixedAixs, -offset.y * added.y + otherScale.z / 2);
break;
case Azimuth.Left:
newPos = new Vector3(-offset.x * added.x + otherScale.x / 2, fixedAixs, 0);
break;
case Azimuth.Right:
newPos = new Vector3(offset.x * added.x - otherScale.x / 2, fixedAixs, 0);
break;
case Azimuth.Up:
newPos = new Vector3(0, fixedAixs, offset.y * added.y - otherScale.z / 2);
break;
case Azimuth.Down:
newPos = new Vector3(0, fixedAixs, -offset.y * added.y + otherScale.z / 2);
break;
default:
break;
}
other.transform.localPosition = newPos;
}
int index = (int)Azimuth.UpperLeft;
void OnGUI()
{
GUIStyle style = new GUIStyle();
style.fontSize = 40;
style.normal.textColor = Color.white;
GUIStyle style2 = new GUIStyle();
style2.fontSize = 20;
style2.normal.textColor = Color.white;
style2.border = new RectOffset(3, 3, 2, 2);
GUI.Label(new Rect(30, 10, 100, 200), dot.ToString(), style);
GUI.Label(new Rect(30, 50, 100, 200), dot_angle.ToString(), style);
GUI.Label(new Rect(30, 100, 100, 200), cross.ToString(), style);
GUI.Label(new Rect(30, 300, 100, 200), fangwei.ToString(), style);
GUI.skin.button.fontSize = 30;
GUI.skin.button.fixedWidth = 250f;
GUI.skin.button.fixedHeight = 100f;
bool isClick = GUI.Button(new Rect(30, 400, 100, 200), m_Azimuth.ToString());
if (isClick)
{
if (index > (int)Azimuth.Down)
{
index = (int)Azimuth.UpperLeft;
}
m_Azimuth = (Azimuth)index;
ChangeAzimuth(m_Azimuth);
index++;
Debug.Log(m_Azimuth.ToString());
}
}
}