Unity实现磁铁效果

所有效果均都参考使用:https://www.zhihu.com/question/39781696   ,包括同作者(Xylt)聊天得知。

前言:刚遇到这个功能,想的其实挺简单,但是做的时候发现其实我想的有点多并且有些问题。

第一版我用的我自己的思路去做的,不使用物理碰撞利用Transform来判断,判断方向和距离。只要As -> Bn的距离等于An->Bs的距离则为异极相吸,反则排斥。但是他会有一个问题,当两磁铁其中有一个具有旋转,不是水平的那么他的距离就会出现不等的问题。这个点始终想不明白。于是有了第二版。

第二版,通过参考文章,我做出来了。大概想法是,在磁铁的两极添加碰撞,并在脚本中赋予两极不同的标识,通过碰撞进行判断,从而达到相吸或者排斥的条件。移动方式使用物理方式进行操作。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Magnet : MonoBehaviour
{
    //最大距离
    [SerializeField]
    float MaxDistance;
    //最远距离
    [SerializeField]
    float MinDistance;
    //最大的力度
    [SerializeField]
    float MaxForce;
    //磁极标识
    [SerializeField]
    ItemType _Type;

    //动画曲线,用来做磁力的变化
    public AnimationCurve forceCurve;
   
    Rigidbody thisRig;
    public ItemType mType
    {
        get
        {
            return _Type;
        }
    }
    private void Awake()
    {
        thisRig = GetComponentInParent<Rigidbody>();
    }
    private void OnTriggerStay(Collider other)
    {
        Magnet script = other.GetComponent<Magnet>();
        if (script == null)
            return;
        Rigidbody otherRig = other.attachedRigidbody;

        //获取两极之间的距离
        float distance = Mathf.Max(MinDistance, Vector3.Distance(this.transform.position, script.transform.position));

        //根据距离获取当前力度
        float forceAmount = Mathf.Min(GetForce(distance), MaxForce);

        //获取方向
        Vector3 forceDir = Vector3.Normalize(this.transform.position - script.transform.position);

        //方向以及力度
        Vector3 force = forceDir * forceAmount;

        //如果同极反方向运动
        if (script.mType == this.mType)   
            force *= -1;

        //因为都是磁铁所以需要给产生碰撞的两极都添加力
        otherRig.AddForceAtPosition(force, script.transform.position);    

        if (thisRig != null)
            thisRig.AddForceAtPosition(-force, script.transform.position);   
    }
    //利用动画曲线对磁力度进行获取,根据两极之前的距离变大或变小。
    float GetForce(float value)
    {
        float var = value / MaxDistance;
        float curveValue = forceCurve.Evaluate(var);
        float farce = MaxForce * curveValue;
        return farce;
    }
}
public enum ItemType
{
    South,
    North,
}

将这个脚本添加到磁铁的两级然后就可以实现磁体的效果了。需要注意的是磁极的碰撞大小以及位置需要测试调节才能达到效果。

如果,运行过程中出现同级吸引之后不会停止而是来回动作,或者排斥时物体不会停止时,请修改物理系统参数,

  1. 将相关物体的碰撞检测方式设为:CountinuousDynamic;
  2. 在ProjectSettings的Physics一栏中,打开Enable Adaptive Force,提高Default Solver Iterations

  3. 限制磁力最大值

  4. 减少相关物体的碰撞大小

写个Bug呢是我处理的时候出现的问题,然后去询问的原作者,原作者告知的。感谢!!!!!!!!

猜你喜欢

转载自blog.csdn.net/chu19970426/article/details/104705228