标签:
游戏中的每个3D对象在世界坐标系里都有坐标。
技能的作用范围可能是圆形,矩形,扇形,三角形等。
那可不可以直接拿 “点”直接与这些形状进行碰撞检测呢!
如果你要的效果不是那么精确,可以允许一点点瑕疵,那么是可行的。
那么这个瑕疵是什么呢?
因为3D物体都有体积,当你肉眼都能看到你的3D模型已经在范围里面,但是为什么技能作用不到它呢?
因为实际取的是3D物体的中心点。当这个中心点真正进入技能范围内,技能才真正作用到他。
如图:中心点还在范围外
如果你不能允许,那这种方式就不适合了。我会在下篇整理更精确的方式。
这里有本书:Real-Time Collision Dectection 中文版
我上传到网盘了:
链接:http://pan.baidu.com/s/1o63VtqE 密码:d5vt
如果你能允许,那么请往下看。
1.点在三角形内
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
using UnityEngine;
using System.Collections;
/// <summary>
/// 点在三角形里面
/// </summary>
public class PointInTriangle : MonoBehaviour
{
public Transform PointTrans;
public float distance = 5f;
public float angle = 30f;
void Update()
{
Quaternion r = this.transform.rotation;
Vector3 f0 = transform.position + (r * Vector3.forward) * distance;
//Debug.DrawLine(transform.position, f0, Color.red);//正前方
Quaternion r0 = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y - angle, transform.rotation.eulerAngles.z);
Vector3 f1 = transform.position + (r0 * Vector3.forward) * distance;
Debug.DrawLine(transform.position, f1, Color.red);//左30度方向
Quaternion r1 = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y + angle, transform.rotation.eulerAngles.z);
Vector3 f2 = transform.position + (r1 * Vector3.forward) * distance;//右30度方向
Debug.DrawLine(transform.position, f2, Color.red);
Debug.DrawLine(f1, f2, Color.red);//连接成一个三角形
Vector3 point = PointTrans.position;
//点是否在一个三角形内
if (MyTool.isINTriangle(point, transform.position, f1, f2))
{
Debug.Log("in");
}
else
{
Debug.Log("not in");
}
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
using UnityEngine;
using System.Collections;
/// <summary>
/// 点在扇形里面
/// </summary>
public class PointInSector : MonoBehaviour
{
public Transform pointTransform;
public float distance = 5f;
public float angle = 30f;
void Update()
{
Quaternion r = this.transform.rotation;
Vector3 f0 = transform.position + (r * Vector3.forward) * distance;
Debug.DrawLine(transform.position, f0, Color.red);//正前方
Quaternion r0 = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y - angle, transform.rotation.eulerAngles.z);
Vector3 f1 = transform.position + (r0 * Vector3.forward) * distance;
Debug.DrawLine(transform.position, f1, Color.red);//左30度方向
Quaternion r1 = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y + angle, transform.rotation.eulerAngles.z);
Vector3 f2 = transform.position + (r1 * Vector3.forward) * distance;//右30度方向
Debug.DrawLine(transform.position, f2, Color.red);
Debug.DrawLine(f1, f2, Color.red);//连接成一个三角形
Vector3 point = pointTransform.position;
Vector3 selfVec = (f0 - this.transform.position).normalized;
Vector3 targetVec = (pointTransform.position - this.transform.position).normalized;
Debug.DrawLine(pointTransform.position, this.transform.position, Color.yellow);
//在左右30度以内
if (Vector3.Dot(selfVec, targetVec) > Mathf.Cos(Mathf.PI / 6.0f))
{
//且在周围distance范围以内,等价于在这个扇形区域!
if ((pointTransform.position - this.transform.position).sqrMagnitude < distance * distance)
{
Debug.Log("in");
}
else
{
Debug.Log("not in");
}
}
else
{
Debug.Log("out of angle");
}
}
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
using UnityEngine;
using System.Collections;
/// <summary>
/// 点在矩形里面
/// </summary>
public class PointInRectangle : MonoBehaviour
{
public Transform pointTransform;
public float length = 5f;
public float width = 5f;
private float half_length;
private float half_width;
void Start()
{
this.half_length = this.length / 2.0f;
this.half_width = this.width / 2.0f;
}
void Update()
{
Quaternion r = transform.rotation;
Vector3 left = (transform.position + (r * Vector3.left) * this.half_length);
Debug.DrawLine(transform.position, left, Color.red);
Vector3 right = (transform.position + (r * Vector3.right) * this.half_length);
Debug.DrawLine(transform.position, right, Color.red);
Vector3 leftEnd = (left + (r * Vector3.forward) * this.width);
Debug.DrawLine(left, leftEnd, Color.red);
Vector3 rightEnd = (right + (r * Vector3.forward) * this.width);
Debug.DrawLine(right, rightEnd, Color.red);
Debug.DrawLine(leftEnd, rightEnd, Color.red);
Vector3 point = pointTransform.position;
//是否在矩形内
if (MyTool.isINRect(point, leftEnd, rightEnd, right, left))
{
Debug.Log("in");
}
else
{
Debug.Log("not in");
}
}
}
|
工具类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
using UnityEngine;
public class MyTool
{
private static float triangleArea(float v0x, float v0y, float v1x, float v1y, float v2x, float v2y)
{
return Mathf.Abs((v0x * v1y + v1x * v2y + v2x * v0y
- v1x * v0y - v2x * v1y - v0x * v2y) / 2f);
}
public static bool isINTriangle(Vector3 point, Vector3 v0, Vector3 v1, Vector3 v2)
{
float x = point.x;
float y = point.z;
float v0x = v0.x;
float v0y = v0.z;
float v1x = v1.x;
float v1y = v1.z;
float v2x = v2.x;
float v2y = v2.z;
float t = triangleArea(v0x, v0y, v1x, v1y, v2x, v2y);
float a = triangleArea(v0x, v0y, v1x, v1y, x, y) + triangleArea(v0x, v0y, x, y, v2x, v2y) + triangleArea(x, y, v1x, v1y, v2x, v2y);
if (Mathf.Abs(t - a) <= 0.01f)
{
return true;
}
else
{
return false;
}
}
private static float Multiply(float p1x, float p1y, float p2x, float p2y, float p0x, float p0y)
{
return ((p1x - p0x) * (p2y - p0y) - (p2x - p0x) * (p1y - p0y));
}
public static bool isINRect(Vector3 point, Vector3 v0, Vector3 v1, Vector3 v2, Vector3 v3)
{
float x = point.x;
float y = point.z;
float v0x = v0.x;
float v0y = v0.z;
float v1x = v1.x;
float v1y = v1.z;
float v2x = v2.x;
float v2y = v2.z;
float v3x = v3.x;
float v3y = v3.z;
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)
return true;
else
return false;
}
}
|
标签:
原文地址:http://www.cnblogs.com/joeshifu/p/4889588.html