- 思路:动量守恒定律。默认所有碰撞为弹性形变,且碰撞后速度loss根据质量直接进行等比分配。
代码语言:javascript
复制//代码1 给主体小球施加z方向的力,F = 50
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class push : MonoBehaviour
{
private Physics ps;
// Start is called before the first frame update
void Start()
{
ps = GetComponent<Physics>();
Debug.Log(Vector3.Reflect(new Vector3(0, 0, 1), new Vector3(1, 0, 0)));
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
ps.setSpeed(new Vector3(0, 0, 1), 50f);
}
}
}
代码语言:javascript
复制//代码2,每个小球的默认物理属性,包含速度等
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Physics : MonoBehaviour
{
[Range(0.001f, 100f)]
public float Mass = 1;
[Range(0f,100f)]
public float drag = 0;
[Range(0f,100f)]
public float AngularDrag = 0;
private Vector3 moveDir;
private float speed;
[Range (0f,float.PositiveInfinity)]
private float friction = 0;
[Range(0f, float.PositiveInfinity)]
private float Angularfriction = 0;
private void Start()
{
friction = drag * Mass * 9.8f;
Angularfriction = drag * AngularDrag;
}
private void Update()
{
if(speed != 0)
Move();
}
private void Move()
{
//用Update直接近似求速度积分
speed -= friction * 0.5f * (Time.deltaTime * Time.deltaTime) * 3600f;
if (speed < 0)
{
speed = 0;
moveDir = Vector3.zero;
}
transform.position = transform.position speed * moveDir * Time.deltaTime;
}
public void setSpeed(Vector3 d,float f)
{
moveDir = Vector3.Normalize(d);
speed = f;
}
public Vector3 getDirection()
{
return moveDir;
}
public float getSpeed()
{
return speed;
}
}
代码语言:javascript
复制//代码3,碰撞检测系统
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ColliderSystem : MonoBehaviour
{
public GameObject[] g;
private bool[,] iscrach;//该作用是禁止在碰撞检测到的时候继续累加碰撞检测,保持操作原子性
void Start()
{
//也可以根据Physics代码块查找
g = GameObject.FindGameObjectsWithTag("HasCollider");
iscrach = new bool[g.Length, g.Length];
}
private void Update()
{
ColliderCheck();
}
void ColliderCheck()
{
for(int i = 0; i < g.Length; i )
for(int j = i 1; j < g.Length; j )
{
if(Vector3.Distance(g[i].transform.position, g[j].transform.position) <= 1f && iscrach[i,j] == false)
{
iscrach[i, j] = true;
Physics g1 = g[i].GetComponent<Physics>();
Physics g2 = g[j].GetComponent<Physics>();
//动量守恒定律
if(g1.Mass * g1.getSpeed() >= g2.Mass * g2.getSpeed())
{
Vector3 reflect = Vector3.Reflect(g1.getDirection(), g[i].transform.position - g[j].transform.position);
g2.setSpeed(-reflect, g1.getSpeed() * (g2.Mass / (g1.Mass g2.Mass)));
g1.setSpeed(reflect, g1.getSpeed() * (g1.Mass / (g1.Mass g2.Mass)));
}
else
{
Vector3 reflect = Vector3.Reflect(g2.getDirection(), g[j].transform.position - g[i].transform.position);
g1.setSpeed(-reflect, g2.getSpeed() * (g2.Mass / (g1.Mass g2.Mass)));
g2.setSpeed(reflect, g2.getSpeed() * (g1.Mass / (g1.Mass g2.Mass)));
}
}
else if(Vector3.Distance(g[i].transform.position, g[j].transform.position) > 1f) iscrach[i, j] = false;
}
}
}