简单物理系统演示

2022-09-21 14:41:40 浏览数 (1)

  • 思路:动量守恒定律。默认所有碰撞为弹性形变,且碰撞后速度loss根据质量直接进行等比分配。

  • 默认所有小球质量为1KG,摩擦系数0.1
  • 演示视频
代码语言: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;
            }
    }
}

0 人点赞