Unity 绘制弹球和台球的运动轨迹

废话不多说,直接上效果图

原理就是创建一个 轨迹球,在第二场景中模拟白球的物理运动轨迹,并记录轨迹! 也就是创建一个不可见的场景,用来模拟球的运动轨迹绘制。

碰撞后,被碰撞物体的运动轨迹绘制 将动量传递给碰撞对象,得到碰撞的对象。 从而记录被碰撞对象的运动轨迹

有两个关键的代码:

调用 physicsScene.Simulate(0.02f);完成轨迹预测;

这个API 需要 Physics.autoSimulation = false;//关闭 物理模拟

 代码如下:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UnityEngine;
using Lean.Touch;
using DG.Tweening;
using UnityEngine.SceneManagement;

public class BallPool : MonoBehaviour
{       
    public List<GameObject> GoBallList = new List<GameObject>();//所有的反射小球
    public Transform trackBallTransform;//轨迹球(即需要物理模拟的小球)
    private Rigidbody2D trackBallRigidbody;//轨迹球的刚体
    private PhysicsScene2D physicsScene;       //物理场景
    public Vector3 vecBallPoint;//轨迹球的位置    

    private void Start()
    {
        CreateBallReflect();//创建反射小球
        CreatePhysicsScene();//创建一个用于模拟的场景
    }

    private void OnEnable()
    {
        LeanTouch.OnFingerDown += OnFingerDown;
        LeanTouch.OnFingerSet += OnFingerSet;
        LeanTouch.OnFingerUp += OnFingerUp;
    }    

    private void OnDisable()
    {
        LeanTouch.OnFingerDown -= OnFingerDown;
        LeanTouch.OnFingerSet -= OnFingerSet;
        LeanTouch.OnFingerUp -= OnFingerUp;
    }

    //创建反射小球
    private void CreateBallReflect()
    {
        //创建轨迹球
        trackBallTransform = ObjectPool.Instance.Spawn("BallTrack", LobbyCtrl.Instance.transform.parent).transform;
        trackBallTransform.name = "TrackBall";
        trackBallTransform.position = vecBallPoint;
        trackBallRigidbody = trackBallTransform.GetComponent<Rigidbody2D>();
        UIHelper.SetActive(false, trackBallTransform);

        //创建20个白色反射小球,并隐藏
        for (int i = 0; i < 20; i++)
        {
            GameObject ball = ObjectPool.Instance.Spawn(Const.Prefab_Obj_BallReflect, transform);
            ball.name = "BallReflect";
            GoBallList.Add(ball);
        }
        for (int i = 0; i < GoBallList.Count; i++)
        {
            UIHelper.SetActive(false, GoBallList[i]);
        }
    }

    //创建一个用于模拟的场景
    private void CreatePhysicsScene()
    {
        var scene = SceneManager.CreateScene("Physics");
        physicsScene = scene.GetPhysicsScene2D();
        //将轨迹球移动到物理场景里
        SceneManager.MoveGameObjectToScene(trackBallTransform.gameObject, scene);
        
    }   

    private void MoveFinger(LeanFinger finger)
    {        
        //显示轨迹球
        UIHelper.SetActive(true, trackBallTransform);
        //关闭 物理
        Physics2D.autoSimulation = false; 
        //每次移动需要重置轨迹球的位置和力
        trackBallTransform.position = ballCtrl.transform.position;
        trackBallRigidbody.velocity = Vector3.zero;

        Vector2 screenPoint = Camera.main.ScreenToWorldPoint(finger.ScreenPosition);
        var dir = (screenPoint - (Vector2)ballCtrl.transform.position).normalized;
        //让轨迹球开始物理模拟
        trackBallRigidbody.AddForce(dir * Const.BallSpeed);

        for (int i = 0; i < GoBallList.Count; i++)
        {
            GameObject ball = GoBallList[i];
            UIHelper.SetActive(true, ball);
            physicsScene.Simulate(0.02f);//必须加这一句,值越小白色反射球间距越小
            ball.transform.position = trackBallTransform.position;//所有的白色反射小球会放置到轨迹球经过的位置上
        }
    }

    //按下
    private void OnFingerDown(LeanFinger finger)
    {                
        MoveFinger(finger);
    }

    //移动
    private void OnFingerSet(LeanFinger finger)
    {       
        MoveFinger(finger);
    }

    //松开
    private void OnFingerUp(LeanFinger finger)
    {        
        //打开物理
        Physics2D.autoSimulation = true;        
    }

    //回收弹球
    void ClearBallList()
    {        
        UIHelper.SetActive(false, trackBallTransform);
        for (int i = 0; i < GoBallList.Count; i++)
        {
            ObjectPool.Instance.Unspawn(GoBallList[i]);
        }
    }   
    
}

猜你喜欢

转载自blog.csdn.net/cuijiahao/article/details/125517363
今日推荐