柚子快报邀请码778899分享:算法实现2D OBB碰撞

http://www.51969.com/

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碰撞

http://www.51969.com/

查看原文