Unity3D 主角面朝方向一定区域内对象角度计算
来源:互联网 发布:数据库的算法 编辑:程序博客网 时间:2024/05/02 02:22
写在前面的话,前两天有个朋友在QQ上问我 如何获取主角面朝方向一定区域中的敌人对象。这个命题看似简单,其实里面蕴含了很多数学方面的东西。今天刚好有时间我就彻底的把这个疑问写在博客中。希望可以帮助到他。
在上代码之前请大家跟我先做几个简单的练习题,角度向量的计算一定要学会,不然后面的东西会很难懂。
1.已知3D坐标,和一个旋转角度,以及一段距离,求目标点的3D坐标。
已知当前点为Target,目标点沿着Target的Y轴旋转30度,沿着Target的X轴延伸10米求目标点的3D坐标?
01
using
UnityEngine;
02
using
System.Collections;
03
04
public
class
Test : MonoBehaviour
05
{
06
07
public
Transform Target;
08
09
void
LateUpdate ()
10
{
11
Quaternion rotation = Quaternion.Euler(0f,30f,0f) * Target.rotation;
12
Vector3 newPos = rotation *
new
Vector3(10f,0f,0f);
13
Debug.DrawLine(newPos,Vector3.zero,Color.red);
14
Debug.Log(
"newpos "
+ newPos +
" nowpos "
+ Target.position +
" distance "
+ Vector3.Distance(newPos,Target.position));
15
}
16
17
}
输出结果 :新坐标 (8.7, 0.0, -5.0) 当前坐标 (0.0, 0.0, 0.0)两点之间的距离 10。
2.已知3D模型的角度求它的向量。
已知3D模型Target,Y轴旋转30度后向前平移。
01
using
UnityEngine;
02
using
System.Collections;
03
04
public
class
Test : MonoBehaviour
05
{
06
07
public
Transform Target;
08
09
void
LateUpdate ()
10
{
11
12
if
(Input.GetMouseButton(0))
13
{
14
Quaternion rotation = Quaternion.Euler(0f,30f,0f) * Target.rotation;
15
Vector3 newPos = rotation * Vector3.forward;
16
Target.Translate(newPos.x,newPos.y,newPos.z);
17
}
18
}
19
20
}
3.已知一个目标点,让模型朝着这个目标点移动。
这是一个比较简单的例子,大家应该都能看明白。
1
Target.transform.LookAt(
new
Vector3 (100f,200f,300f));
2
Target.Translate(Vector3.forward);
这里我要说的就是Vector3.forward ,它等价与 new Vector3(0,0,1);它并不是一个坐标,它是一个标准向量,方向是沿着Z轴向前。这样平移一次的距离就是1米, 如果Vector3.forward * 100那么一次平移的距离就是100米。
在看看下面这段代码
1
Vector3 vecn = (TargetCube.position - Target.position).normalized;
2
3
Target.Translate(vecn *0.1f);
用向量减去一个向量求出它们的差值,normalized 是格式化向量,意思是把它们之间向量格式化到1米内。这样就可以更加精确的计算一次平移的距离了 vecn *0.1f 就标示一次平移1分米,蛤蛤。
向量不仅可以进行X Y Z轴的移动,同样可以进行旋转 ,下面这段代码就是让向量沿着Y轴旋转30度。
1
Vector3 vecn = (TargetCube.position - Target.position).normalized;
2
3
vecn = Quaternion.Euler(0f,30f,0f) * vecn;
4
5
Target.Translate(vecn *0.1f);
如果上述三道简单的练习题 你都能了然于心的话,那么本文最大的难题我相信也不会是什么难事,继续阅读吧。
假设我们需要计算主角面前5米内所有的对象时。以主角为圆心计算面前5米外的一个点,为了让大家看清楚我现将这条线绘制出来。
1
private
float
distance = 5f;
2
void
Update ()
3
{
4
Quaternion r= transform.rotation;
5
Vector3 f0 = (transform.position + (r *Vector3.forward) * distance);
6
Debug.DrawLine(transform.position,f0,Color.red);
7
}
如下图所,我们已经将这两个点计算出来了。此时你可以动态的编辑主角Y轴的坐标,这个点永远都是沿着主角当前角度面前5米以外的点。
接下来,我们需要计算主角面前的一个发散性的角度。假设主角看到的是向左30度,向右30度在这个区域。
01
private
float
distance = 5f;
02
void
Update ()
03
{
04
Quaternion r= transform.rotation;
05
Vector3 f0 = (transform.position + (r *Vector3.forward) * distance);
06
Debug.DrawLine(transform.position,f0,Color.red);
07
08
Quaternion r0= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y - 30f,transform.rotation.eulerAngles.z);
09
Quaternion r1= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y + 30f,transform.rotation.eulerAngles.z);
10
11
Vector3 f1 = (transform.position + (r0 *Vector3.forward) * distance);
12
Vector3 f2 = (transform.position + (r1 *Vector3.forward) * distance);
13
14
Debug.DrawLine(transform.position,f1,Color.red);
15
Debug.DrawLine(transform.position,f2,Color.red);
16
17
Debug.DrawLine(f0,f1,Color.red);
18
Debug.DrawLine(f0,f2,Color.red);
19
}
如下图所示,这时主角面前的区域就计算出来了。看起来就是两个三角形之间的区域。
最后就是简单的套用公式,计算一个点是否在三角形内,在本文中就是计算敌人的点是否在面前的这两个三角形内。
01
using
UnityEngine;
02
using
System.Collections;
03
04
public
class
MyTest : MonoBehaviour {
05
06
public
Transform cube;
07
08
private
float
distance = 5f;
09
void
Update ()
10
{
11
Quaternion r= transform.rotation;
12
Vector3 f0 = (transform.position + (r *Vector3.forward) * distance);
13
Debug.DrawLine(transform.position,f0,Color.red);
14
15
Quaternion r0= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y - 30f,transform.rotation.eulerAngles.z);
16
Quaternion r1= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y + 30f,transform.rotation.eulerAngles.z);
17
18
Vector3 f1 = (transform.position + (r0 *Vector3.forward) * distance);
19
Vector3 f2 = (transform.position + (r1 *Vector3.forward) * distance);
20
21
Debug.DrawLine(transform.position,f1,Color.red);
22
Debug.DrawLine(transform.position,f2,Color.red);
23
24
Debug.DrawLine(f0,f1,Color.red);
25
Debug.DrawLine(f0,f2,Color.red);
26
27
Vector3 point = cube.position;
28
29
if
(isINTriangle(point,transform.position,f1,f0) || isINTriangle(point,transform.position,f2,f0) )
30
{
31
Debug.Log(
"cube in this !!!"
);
32
}
else
33
{
34
Debug.Log(
"cube not in this !!!"
);
35
}
36
37
}
38
39
private
float
triangleArea(
float
v0x,
float
v0y,
float
v1x,
float
v1y,
float
v2x,
float
v2y)
40
{
41
return
Mathf.Abs((v0x * v1y + v1x * v2y + v2x * v0y
42
- v1x * v0y - v2x * v1y - v0x * v2y) / 2f);
43
}
44
45
bool
isINTriangle(Vector3 point,Vector3 v0,Vector3 v1,Vector3 v2)
46
{
47
float
x = point.x;
48
float
y = point.z;
49
50
float
v0x = v0.x;
51
float
v0y = v0.z;
52
53
float
v1x = v1.x;
54
float
v1y = v1.z;
55
56
float
v2x = v2.x;
57
float
v2y = v2.z;
58
59
float
t = triangleArea(v0x,v0y,v1x,v1y,v2x,v2y);
60
float
a = triangleArea(v0x,v0y,v1x,v1y,x,y) + triangleArea(v0x,v0y,x,y,v2x,v2y) + triangleArea(x,y,v1x,v1y,v2x,v2y);
61
62
if
(Mathf.Abs(t - a) <= 0.01f)
63
{
64
return
true
;
65
}
else
66
{
67
return
false
;
68
}
69
}
70
}
如下图所示,如果箱子对象是主角的视野中就会检测到。
注意,上图中我的视野选择了两个三角形,如果你需要视野目标点是椭圆形的话,那么可以多设置一些三角形。但是这样就会非常消耗效率,我觉得这里完全可以使用1个三角形,,只是正对的目标点会出现一些偏差,影响其实并不会很大。如下图所示
代码简单的修改一下即可。
01
using
UnityEngine;
02
using
System.Collections;
03
04
public
class
MyTest : MonoBehaviour {
05
06
public
Transform cube;
07
08
private
float
distance = 5f;
09
void
Update ()
10
{
11
Quaternion r= transform.rotation;
12
Vector3 f0 = (transform.position + (r *Vector3.forward) * distance);
13
Debug.DrawLine(transform.position,f0,Color.red);
14
15
Quaternion r0= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y - 30f,transform.rotation.eulerAngles.z);
16
Quaternion r1= Quaternion.Euler(transform.rotation.eulerAngles.x,transform.rotation.eulerAngles.y + 30f,transform.rotation.eulerAngles.z);
17
18
Vector3 f1 = (transform.position + (r0 *Vector3.forward) * distance);
19
Vector3 f2 = (transform.position + (r1 *Vector3.forward) * distance);
20
21
Debug.DrawLine(transform.position,f1,Color.red);
22
Debug.DrawLine(transform.position,f2,Color.red);
23
Debug.DrawLine(f1,f2,Color.red);
24
25
Vector3 point = cube.position;
26
27
if
(isINTriangle(point,transform.position,f1,f2))
28
{
29
Debug.Log(
"cube in this !!!"
);
30
}
else
31
{
32
Debug.Log(
"cube not in this !!!"
);
33
}
34
35
}
36
37
private
float
triangleArea(
float
v0x,
float
v0y,
float
v1x,
float
v1y,
float
v2x,
float
v2y)
38
{
39
return
Mathf.Abs((v0x * v1y + v1x * v2y + v2x * v0y
40
- v1x * v0y - v2x * v1y - v0x * v2y) / 2f);
41
}
42
43
bool
isINTriangle(Vector3 point,Vector3 v0,Vector3 v1,Vector3 v2)
44
{
45
float
x = point.x;
46
float
y = point.z;
47
48
float
v0x = v0.x;
49
float
v0y = v0.z;
50
51
float
v1x = v1.x;
52
float
v1y = v1.z;
53
54
float
v2x = v2.x;
55
float
v2y = v2.z;
56
57
float
t = triangleArea(v0x,v0y,v1x,v1y,v2x,v2y);
58
float
a = triangleArea(v0x,v0y,v1x,v1y,x,y) + triangleArea(v0x,v0y,x,y,v2x,v2y) + triangleArea(x,y,v1x,v1y,v2x,v2y);
59
60
if
(Mathf.Abs(t - a) <= 0.01f)
61
{
62
return
true
;
63
}
else
64
{
65
return
false
;
66
}
67
}
68
}
上面我们介绍了三角形判断,当然也可以通过矩形来判断是否相交。。
代码:
01
using
UnityEngine;
02
using
System.Collections;
03
04
public
class
MyTest : MonoBehaviour {
05
06
public
Transform cube;
07
08
private
float
distance = 5f;
09
void
Update ()
10
{
11
Quaternion r= transform.rotation;
12
Vector3 left = (transform.position + (r *Vector3.left) * distance);
13
Debug.DrawLine(transform.position,left,Color.red);
14
15
Vector3 right = (transform.position + (r *Vector3.right) * distance);
16
Debug.DrawLine(transform.position,right,Color.red);
17
18
Vector3 leftEnd = (left + (r *Vector3.forward) * distance);
19
Debug.DrawLine(left,leftEnd,Color.red);
20
21
Vector3 rightEnd = (right + (r *Vector3.forward) * distance);
22
Debug.DrawLine(right,rightEnd,Color.red);
23
24
Debug.DrawLine(leftEnd,rightEnd,Color.red);
25
26
Vector3 point = cube.position;
27
28
if
(isINRect(point,leftEnd,rightEnd,right,left))
29
{
30
Debug.Log(
"cube in this !!!"
);
31
}
else
32
{
33
Debug.Log(
"cube not in this !!!"
);
34
}
35
36
}
37
38
private
float
Multiply(
float
p1x ,
float
p1y,
float
p2x,
float
p2y,
float
p0x,
float
p0y)
39
{
40
return
((p1x - p0x) * (p2y - p0y) - (p2x - p0x) * (p1y - p0y));
41
}
42
43
bool
isINRect(Vector3 point,Vector3 v0,Vector3 v1,Vector3 v2,Vector3 v3)
44
{
45
float
x = point.x;
46
float
y = point.z;
47
48
float
v0x = v0.x;
49
float
v0y = v0.z;
50
51
float
v1x = v1.x;
52
float
v1y = v1.z;
53
54
float
v2x = v2.x;
55
float
v2y = v2.z;
56
57
float
v3x = v3.x;
58
float
v3y = v3.z;
59
60
if
(Multiply(x,y, v0x,v0y, v1x,v1y) * Multiply(x,y, v3x,v3y, v2x,v2y) <= 0 && Multiply(x,y, v3x,v3y, v0x,v0y) * Multiply(x,y, v2x,v2y, v1x,v1y) <= 0)
61
return
true
;
62
else
63
return
false
;
64
65
}
66
67
}
如果大家看了这篇文章后发现在你的项目中还有一些比较麻烦的角度与向量的算法,欢迎在下面留言给我,如果我有时间我会第一时间把方法贴在博客中。互相学习互相进步,加油!哇咔咔。。
马上过年了,雨松MOMO在这里祝福大家2013年幸幸福福的过日子,嘿嘿。
2013年4月补充
感谢楼下朋友给我的留言。, 我在补充一下这篇博客。
01
using
UnityEngine;
02
using
System.Collections;
03
04
public
class
NewBehaviourScript : MonoBehaviour {
05
06
public
Transform target;
07
08
void
Update()
09
{
10
11
float
distance = Vector3.Distance(target.position,transform.position);
12
13
Quaternion right = transform.rotation * Quaternion.AngleAxis(30,Vector3.up);
14
Quaternion left = transform.rotation * Quaternion.AngleAxis(30,Vector3.down);
15
16
Vector3 n = transform.position + (Vector3.forward * distance);
17
Vector3 leftPoint = left * n ;
18
Vector3 rightPoint = right *n ;
19
20
Debug.DrawLine(transform.position,leftPoint,Color.red);
21
Debug.DrawLine(transform.position,rightPoint,Color.red);
22
Debug.DrawLine(rightPoint,leftPoint,Color.red);
23
24
}
25
}
这里我以角色左右个30度。 这样就可以根据两个模型的距离以及角度来判断了。。
转载自:http://www.xuanyusong.com/archives/1977
- Unity3D 主角面朝方向一定区域内对象角度计算
- 主角面朝方向一定区域内对象角度计算
- Unity3D研究院之主角面朝方向一定区域内对象角度计算
- Unity3D研究院之主角面朝方向一定区域内对象角度计算
- Unity3D研究院之主角面朝方向一定区域内对象角度计算(四十五)
- Unity3D研究院之主角面朝方向一定区域内对象角度计算(四十五)
- Unity3D研究院之主角面朝方向一定区域内对象角度计算(四十五)
- Unity3D研究院之主角面朝方向一定区域内对象角度计算
- Unity3D研究院之主角面朝方向一定区域内对象角度计算
- Unity3D研究院之主角面朝方向一定区域内对象角度计算(四十五)
- Unity3D研究院之主角面朝方向一定区域内对象角度计算(四十五)
- Unity3D研究院之主角面朝方向一定区域内对象角度计算
- Unity3D研究院之主角面朝方向一定区域内对象角度计算
- Unity3D——主角面朝方向一定区域内对象角度计算
- Unity3D研究院之主角面朝方向一定区域内对象角度计算
- 主角面朝方向一定区域内对象角度计算(点是否在扇形区域检测)
- 一定区域内对象 用的比较多
- Unity)判断敌人是否位于主角正前方一定角度方位内
- 北风网:学完JAVA后的就业方向
- 【OpenCV入门教程之四】 ROI区域图像叠加&初级图像混合 全剖析
- yum源导入KEY值----warning: rpmts_HdrFromFdno: Header V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY
- 归并排序--Java
- U-boot分析第0章------------------ 编译烧写
- Unity3D 主角面朝方向一定区域内对象角度计算
- 一位ACMer过来人的心得
- JAVA环境搭建
- ACM都要学些什么
- linux笔试题
- SQL 函数总结说明
- (advanced) 动态规划 UVA 1437 - String painter
- "小城春秋"原型梁惠贞:1932年被捕 牺牲时仅26岁
- “传统行业”决胜“互联网公司”