柚子快报邀请码778899分享:算法实现2D OBB碰撞
box
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DrawLine : MonoBehaviour {
public Vector3[] p = new Vector3[4];
public Vector3 up { get; set; }
public Vector3 right { get; set; }
private Cube _cube1;
public Cube cube1 {
get {
if (_cube1 == null) {
_cube1 = new Cube();
_cube1.halfScale = 1;
}
return _cube1;
}
}
public Matrix4x4 matrix;
public Color color = Color.green;
private void OnDrawGizmos() {
Gizmos.color = color;
Vector3 pos = transform.position;
//设置与transform相同矩阵
matrix = Matrix4x4.TRS(pos, transform.rotation, transform.lossyScale);
up = new Vector3(matrix[0, 1], matrix[1, 1], matrix[2, 1]);
right = new Vector3(matrix[0, 0], matrix[1, 0], matrix[2, 0]);
p[0] = up - right + pos;
p[1] = -up - right + pos;
p[2] = -up + right + pos;
p[3] = up + right + pos;
Gizmos.DrawLine(p[0], p[1]);
Gizmos.DrawLine(p[1], p[2]);
Gizmos.DrawLine(p[2], p[3]);
Gizmos.DrawLine(p[3], p[0]);
}
}
public class Cube {
public Vector3 center;
public float halfScale;
public Quaternion rotate;
public Vector3 GetPoint1 => center + new Vector3(-halfScale, halfScale, 0);
public Vector3 GetPoint2 => center + new Vector3(-halfScale, -halfScale, 0);
public Vector3 GetPoint3 => center + new Vector3(halfScale, -halfScale, 0);
public Vector3 GetPoint4 => center + new Vector3(halfScale, halfScale, 0);
}
检查是否碰撞
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColliderCheck : MonoBehaviour {
public DrawLine cube1x;
public DrawLine cube2x;
public float lineLength;
public bool check;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
private void OnDrawGizmos() {
//判断 cube1 与 cube2 是否相交
//获取cube2 在 cube的up 和 right 轴上的投影
check = CheckIsAxis(cube1x, cube2x) && CheckIsAxis(cube2x, cube1x);
if (check) {
cube1x.color = Color.red;
cube2x.color = Color.red;
} else {
cube1x.color = Color.green;
cube2x.color = Color.green;
}
if (Input.GetKeyDown(KeyCode.K)) {
}
}
///
/// 从矩阵获取坐标
///
///
///
public Vector3 GetPosition(Matrix4x4 matrix) {
var x = matrix.m03;
var y = matrix.m13;
var z = matrix.m23;
return new Vector3(x, y, z);
}
///
/// 从矩阵获取旋转
///
///
///
public Quaternion GetRotation(Matrix4x4 matrix) {
//m11 + m22 + m33 = 4w^2
float qw = Mathf.Sqrt(1f + matrix.m00 + matrix.m11 + matrix.m22) / 2;
float w = 4 * qw;
float qx = (matrix.m21 - matrix.m12) / w;
float qy = (matrix.m02 - matrix.m20) / w;
float qz = (matrix.m10 - matrix.m01) / w;
return new Quaternion(qx, qy, qz, qw);
}
///
/// 从矩阵获取缩放
///
///
///
public static Vector3 GetScale(Matrix4x4 m) {
var x = Mathf.Sqrt(m.m00 * m.m00 + m.m01 * m.m01 + m.m02 * m.m02);
var y = Mathf.Sqrt(m.m10 * m.m10 + m.m11 * m.m11 + m.m12 * m.m12);
var z = Mathf.Sqrt(m.m20 * m.m20 + m.m21 * m.m21 + m.m22 * m.m22);
return new Vector3(x, y, z);
}
private bool CheckIsAxis(DrawLine cube1, DrawLine cube2) {
//可得y轴上的最小值与最大值
NewMethod(cube1, cube2, cube1.up, out var maxValue, out var minValue);
//Debug.Log(minValue + " " +maxValue);
//判断y轴是否重合
bool isOverLayY = false;
if (maxValue <= cube1.cube1.halfScale && maxValue >= -cube1.cube1.halfScale) {
isOverLayY = true;
}
if (minValue <= cube1.cube1.halfScale && minValue >= -cube1.cube1.halfScale) {
isOverLayY = true;
}
//判断x轴
NewMethod(cube1, cube2, cube1.right, out var maxValue2, out var minValue2);
bool isOverLayX = false;
if (maxValue2 <= cube1.cube1.halfScale && maxValue2 >= -cube1.cube1.halfScale) {
isOverLayX = true;
}
if (minValue2 <= cube1.cube1.halfScale && minValue2 >= -cube1.cube1.halfScale) {
isOverLayX = true;
}
if (isOverLayX && isOverLayY) {
return true;
}
return false;
}
private void NewMethod(DrawLine cube1, DrawLine cube2, Vector3 onNormal ,out float maxValue, out float minValue) {
float[] yArray = new float[4];
maxValue = 0;
minValue = 0;
for (int i = 0; i < 4; i++) {
Vector3 cube1Pos = cube1.transform.position;
var line = Vector3.Project(cube2.p[i] - cube1Pos, onNormal);
float yValue = line.magnitude;
yArray[i] = yValue;
//Debug.Log(yValue);
if (i == 0) {
maxValue = yValue;
minValue = yValue;
} else {
if (yValue > maxValue) {
maxValue = yValue;
}
if (yValue < minValue) {
minValue = yValue;
}
}
}
}
}
2D凸多边形碰撞检测算法GJK + EPA
https://zhuanlan.zhihu.com/p/178841676
柚子快报邀请码778899分享:算法实现2D OBB碰撞
发表评论