Unity : pool game emulator : The cue ball didn't bounce back as expected; instead, it continued to travel along the table's edge

huangapple go评论53阅读模式
英文:

Unity : pool game emulator : The cue ball didn't bounce back as expected; instead, it continued to travel along the table's edge

问题

以下是您提供的内容的中文翻译:

球杆在与桌边碰撞后,没有如预期般反弹;相反,它继续沿着桌边行进,紧紧贴着边缘。

仿真
Unity : pool game emulator : The cue ball didn't bounce back as expected; instead, it continued to travel along the table's edge

以下是边缘和球的物理材料:

球的物理材料
Unity : pool game emulator : The cue ball didn't bounce back as expected; instead, it continued to travel along the table's edge

边缘的物理材料
Unity : pool game emulator : The cue ball didn't bounce back as expected; instead, it continued to travel along the table's edge

我尝试过调整各种系数,但可能会导致过度的弹性或球仍然继续沿着桌子的边缘行进。

以下是提供球杆速度和方向的C#代码:

using System.IO;
using UnityEngine;
using System.Collections;

public class CueBallController : MonoBehaviour
{
    private string cueball_position_Path = "D:/Unity Project/testtest/Assets/Resources/cueball_position.json";
    private string HitParams_Path = "D:/Unity Project/testtest/Assets/Resources/HitParams.json";

    [System.Serializable]
    public class HitParams
    {
        public float HitSpeed;
        public Vector3 HitDirection;
    }

    HitParams LasthitParams;

    private Rigidbody rb;

    public float stationaryThreshold = 0.01f;
    private bool allBallsStationary = false;

    // Start is called before the first frame update
    void Start()
    {
        LoadInitialPosition(cueball_position_Path);
        rb = GetComponent<Rigidbody>();
        LasthitParams = new HitParams();
    }

    // Update is called once per frame
    void Update()
    {
        allBallsStationary = CheckIfAllBallsAreStationary();

        if (allBallsStationary)
        {
            // 从JSON文件加载初始参数
            HitParams newHitParams = LoadHitParams(HitParams_Path);

            if (newHitParams != null && (newHitParams.HitSpeed != LasthitParams.HitSpeed || newHitParams.HitDirection != LasthitParams.HitDirection))
            {
                // 规范化初始方向并应用初始速度
                Vector3 hitVelocity = newHitParams.HitDirection.normalized * newHitParams.HitSpeed;

                StartCoroutine(MoveWithDelay(2.0f, hitVelocity));

                LasthitParams = newHitParams;
            }
        }
    }

    private void LoadInitialPosition(string path)
    {
        if (File.Exists(path))
        {
            string json = File.ReadAllText(path);
            Vector3 position = JsonUtility.FromJson<Vector3>(json);
            transform.position = position;
        }
        else
        {
            Debug.LogError("未找到JSON文件:" + path);
        }
    }

    private IEnumerator MoveWithDelay(float delay, Vector3 hitVelocity)
    {
        yield return new WaitForSeconds(delay);

        rb.velocity = hitVelocity;
    }

    private HitParams LoadHitParams(string path)
    {
        if (File.Exists(path))
        {
            string json = File.ReadAllText(path);
            HitParams loadedHitParams = JsonUtility.FromJson<HitParams>(json);
            return loadedHitParams;
        }
        else
        {
            Debug.LogError("未找到JSON文件:" + path);
            return null;
        }
    }

    private bool CheckIfAllBallsAreStationary()
    {
        GameObject[] balls = GameObject.FindGameObjectsWithTag("Ball");
        float angularThreshold = 0.01f;

        foreach (GameObject ball in balls)
        {
            Rigidbody ballRigidbody = ball.GetComponent<Rigidbody>();

            if (ballRigidbody != null &&
                (ballRigidbody.velocity.magnitude > stationaryThreshold ||
                ballRigidbody.angularVelocity.magnitude > angularThreshold))
            {
                return false;
            }
        }

        if (!rb.IsSleeping()) return false;

        return true;
    }
}
英文:

The cue ball, after colliding with the table edge, didn't bounce back as expected; instead, it continued to travel along the table's rail, closely hugging its edge.

emulation
Unity : pool game emulator : The cue ball didn't bounce back as expected; instead, it continued to travel along the table's edge

The following are the physical materials of the edge and the ball:

ball physical material
Unity : pool game emulator : The cue ball didn't bounce back as expected; instead, it continued to travel along the table's edge

edge physical material
Unity : pool game emulator : The cue ball didn't bounce back as expected; instead, it continued to travel along the table's edge

I have tried adjusting various coefficients, but it may either result in excessive elasticity or the ball still continuing to travel along the table's edge.

The following is the C# code which provide the velocity and direction of cue ball

using System.IO;
using UnityEngine;
using System.Collections;

public class CueBallController : MonoBehaviour
{
    private string cueball_position_Path = &quot;D:/Unity Project/testtest/Assets/Resources/cueball_position.json&quot;;
    private string HitParams_Path = &quot;D:/Unity Project/testtest/Assets/Resources/HitParams.json&quot;;

    [System.Serializable]
    public class HitParams
    {
        public float HitSpeed;
        public Vector3 HitDirection;
    }

    HitParams LasthitParams;

    private Rigidbody rb;

    public float stationaryThreshold = 0.01f;
    private bool allBallsStationary = false;

    // Start is called before the first frame update
    void Start()
    {
        LoadInitialPosition(cueball_position_Path);
        rb = GetComponent&lt;Rigidbody&gt;();
        LasthitParams = new HitParams();
    }

    // Update is called once per frame
    void Update()
    {
        allBallsStationary = CheckIfAllBallsAreStationary();

        if (allBallsStationary)
        {
            // Load initial parameters from JSON file
            HitParams newHitParams = LoadHitParams(HitParams_Path);

            if (newHitParams != null &amp;&amp; (newHitParams.HitSpeed != LasthitParams.HitSpeed || newHitParams.HitDirection != LasthitParams.HitDirection))
            {
                // Normalize the initial direction and apply the initial speed
                Vector3 hitVelocity = newHitParams.HitDirection.normalized * newHitParams.HitSpeed;

                StartCoroutine(MoveWithDelay(2.0f, hitVelocity));

                LasthitParams = newHitParams;
            }
        }
    }

    private void LoadInitialPosition(string path)
    {
        if (File.Exists(path))
        {
            string json = File.ReadAllText(path);
            Vector3 position = JsonUtility.FromJson&lt;Vector3&gt;(json);
            transform.position = position;
        }
        else
        {
            Debug.LogError(&quot;JSON file not found at: &quot; + path);
        }
    }

    private IEnumerator MoveWithDelay(float delay, Vector3 hitVelocity)
    {
        yield return new WaitForSeconds(delay);

        rb.velocity = hitVelocity;
    }

    private HitParams LoadHitParams(string path)
    {
        if (File.Exists(path))
        {
            string json = File.ReadAllText(path);
            HitParams loadedHitParams = JsonUtility.FromJson&lt;HitParams&gt;(json);
            return loadedHitParams;
        }
        else
        {
            Debug.LogError(&quot;JSON file not found at: &quot; + path);
            return null;
        }
    }

    private bool CheckIfAllBallsAreStationary()
    {
        GameObject[] balls = GameObject.FindGameObjectsWithTag(&quot;Ball&quot;);
        float angularThreshold = 0.01f;

        foreach (GameObject ball in balls)
        {
            Rigidbody ballRigidbody = ball.GetComponent&lt;Rigidbody&gt;();

            if (ballRigidbody != null &amp;&amp;
                (ballRigidbody.velocity.magnitude &gt; stationaryThreshold ||
                ballRigidbody.angularVelocity.magnitude &gt; angularThreshold))
            {
                return false;
            }
        }

        if (!rb.IsSleeping()) return false;

        return true;
    }
}

答案1

得分: 3

这个问题与默认的物理配置有关。低速度碰撞被视为非弹性碰撞,弹跳被忽略(即使在物理材质中设置了也是如此)。这是为了在有一堆缓慢移动的刚体相互碰撞时平稳物理模拟。

对于3D物理,你需要在Edit->Project Settings->Physics下降Bounce Threshold

对于2D物理,你需要在Edit->Project Settings->Physics 2D下降velocityThreshold

不要将值设置得太低,大约0.1应该足够。

英文:

This issue has to do with the default physics configuration. Low velocity impacts are treated as inelastic collisions and the bounce is ignored (even if you set it up in your physics material). This is done to help calm down the physics simulation when you have a pile of slow moving rigid bodies all colliding with each other.

For 3D physics you need to lower the Bounce Threshold under Edit-&gt;Project Settings-&gt;Physics

For 2D physcis you need to lower the velocityThreshold under Edit-&gt;Project Settings-&gt;Physics 2D

Don't make the value too low, something like 0.1 should be enough.

huangapple
  • 本文由 发表于 2023年5月6日 22:50:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76189524.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定