Unity 进阶 之 判断基于物体所处位置(前后左右)/ 方法原理 /注意事项的简单整理
目录
Unity 进阶 之 判断基于物体所处位置(前后左右)/ 方法原理 /注意事项的简单整理
一、简单介绍
Unity中的一些知识点整理。
本节简单介绍在Unity开发中的,判断某个物体在某个物体的位置(相对的前后左右判断),便于根据位置进行一些其他的操作,如果你有新的方式也可以留言,多谢。
二、实现原理
1、在Unity中,使用点积进行前后的判断
Vector3 dir = target.position - transform.position; //位置差,方向
Vector3.Dot(transform.forward, dir);
返回值为正时,目标在自己的前方,反之在自己的后方
2、在Unity中,使用叉积的 y 值进行左右判断
Vector3.Cross(transform.forward, target.position).y
返回值为正时,目标在自己的右方,反之在自己的左方
(为什么取y呢 ,因为 transform.forward实际上是 (0,0,1)*rotation, 也就是只有z有值,
cross出来,就只有 y是计算 x和z 的情况,x是计算 y的情况,z是0;因此 左右关系,是由x和z决定的。)
三、注意事项
1、一个相对另一个物体的判断,最好使用他们间的相对位置判断最后准确,这样可以避免判断的错误
2、实际应用中,合理的使用这种关系,和变换这种关系的使用,拓展出一些新功能的使用,大家结合实际开发使用即可
四、效果预览
五、实现步骤
1、打开 Unity ,新建空工程
2、在场景中,布局场景,用于演示
3、创建脚本,一个用来封装判断函数,一个用来测试函数功能
4、把测试脚本挂载到场景中,并且对应赋值
5、运行场景,效果如上,随着 BaseTransform 转动 或者 Player 移动到不同位置,打印结果就会相应结果
六、关键代码
1、JudgeIsForwardRightBaseSomeOneTransfrom
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace XANUtils {
/// <summary>
/// 判断前后左右的封装
/// </summary>
public class JudgeIsForwardRightBaseSomeOneTransfrom
{
/// <summary>
/// 判断在基于位置的是否在前后
/// </summary>
/// <param name="baseTrans"></param>
/// <param name="dir"></param>
/// <returns>true:前;false:后</returns>
public static bool IsForward(Transform baseTrans, Vector3 pos) {
return GetIsForwardValue(baseTrans, pos) >= 0 ? true:false;
}
/// <summary>
/// 判断在基于位置的是否在左右
/// </summary>
/// <param name="baseTrans"></param>
/// <param name="dir"></param>
/// <returns>true:右;false:左</returns>
public static bool IsRight(Transform baseTrans, Vector3 pos)
{
return GetIsRightValue(baseTrans, pos) >= 0 ? true : false;
}
// 大于0,前
// pos 为 0 ,结果会出错 (做好是相对位置)
public static float GetIsForwardValue(Transform baseTrans, Vector3 pos)
{
return Vector3.Dot(baseTrans.forward, pos - baseTrans.position);
}
// 大于0,右边
// pos 为 0 ,结果会出错(做好是相对位置)
public static float GetIsRightValue(Transform baseTrans, Vector3 pos)
{
return Vector3.Cross(baseTrans.forward, pos - baseTrans.position).y;
}
}
}
2、TestJudgeIsForwardRightBaseSomeOneTransfrom
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XANUtils;
namespace TestSpace {
public class TestJudgeIsForwardRightBaseSomeOneTransfrom : MonoBehaviour
{
public Transform BaseTransform;
public Transform NeedJudageTrans;
// Update is called once per frame
void Update()
{
if (BaseTransform != null && NeedJudageTrans != null)
{
bool isForward = JudgeIsForwardRightBaseSomeOneTransfrom.IsForward(BaseTransform, NeedJudageTrans.position);
bool isRight = JudgeIsForwardRightBaseSomeOneTransfrom.IsRight(BaseTransform, NeedJudageTrans.position);
Debug.LogWarning(GetType() + "/Update()/" + (isForward ? "前" : "后"));
Debug.LogWarning(GetType() + "/Update()/" + (isRight ? "右" : "左"));
}
else {
Debug.LogError(GetType()+ "/Update()/ BaseTransform or NeedJudageTrans is null !! ");
}
}
}
}
七、附录
点积
判断两个物体的位置 关系,是可以通过 这个 cos<a,b> 来判断,知道了这个余玄值,就可以知道 这个角度了。
几何的定义: a·b=|a|*|b|*cos<a,b>
对于n维度代数定义:
它在Unity中 调用是通过Vector3.Dot(),Unity中使用的也是代数公式
public static float Dot(Vector3 lhs, Vector3 rhs)
{
return (float) ((double) lhs.x * (double) rhs.x + (double) lhs.y * (double) rhs.y + (double) lhs.z * (double) rhs.z);
}
如何判断的方位:
使用 a 物体的transform.forward向量与 a 物体到 b 的方向做点击就可以得到这个余弦值了
a 到 b 的方向: otherObj.transform.position – transform.position
transform.forward 是玩家正面朝向 方向
大于0则面对,否则则背对着。当然这个计算也会有一点误差,但大致够用。
因为求的角度用的是 单位向量,所以可以直接求得cos<a,b>
这个角度值 还可以用来判断是否在视野内,一般情况下人的视野是在124度内,游戏里一般是限制在90度左右,视距就直接是两点之间的距离了。
a·b= |a| *|b| * cos<a,b> => a·b= |1|
cos<a,b>的 含义图:
作用:
- 是光照模型的应用,漫反射,高光的计算,diffuse=0.5+0.5*dot(n,l) ,n是法线方向,l是光照方向, 高光saturate(pow(dot(n,h),_Gloss))其中,h是 (viewDir+worldLightDir)/2
- 是判断方位,角度,视野
- 是 几何意义可以是求b在 a的投影
- 等等
叉积
是一种在向量空间中向量的二元运算。与点积不同,它的运算结果是一个向量而不是一个标量。并且两个向量的叉积与这两个向量和垂直。其应用也十分广泛,通常应用于物理学光学和计算机图形学中。
叉积的定义: c =a x b 其中a,b,c均为向量。即两个向量的叉积得到的还是向量!
性质:
- c⊥a,c⊥b,即向量c垂直与向量a,b所在的平面 。
- 模长|c|=|a||b|sin<a,b>
- 满足右手法则 。从这点我们有axb ≠ bxa,而axb = – bxa。所以我们可以使用叉积的正负值来判断向量a,b的相对位置,即向量b是处于向量a的顺时针方向还是逆时针方向。
参考博文:https://blog.csdn.net/qq2512667/article/details/79841333/