Unity implements magnet effect

All effects are referred to: https://www.zhihu.com/question/39781696 , including chatting with the author (Xylt).

Preface: When I first encountered this function, I thought it was quite simple, but when I did it, I found that I actually thought a lot and had some problems.

In the first version, I used my own ideas to do it. I didn't use physical collisions and used Transform to judge, judge the direction and distance. As long as the distance of As -> Bn is equal to the distance of An -> Bs, it is heteropolar attraction, otherwise it is repulsive. But he will have a problem, when one of the two magnets has a rotation and is not horizontal, then his distance will be unequal. I still don't understand this point. Hence the second edition.

The second edition, by referring to the article, I made it. The general idea is to add collisions to the two poles of the magnet, and give the two poles different signs in the script, and judge through collisions, so as to achieve the condition of attraction or repulsion. The mobile method uses physical methods to operate.

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,
}

Add this script to the two stages of the magnet and you can achieve the magnet effect. It should be noted that the collision size and position of the magnetic poles need to be tested and adjusted to achieve the effect.

If, during the running process, the same-level attraction does not stop but moves back and forth, or the object does not stop when repelling, please modify the physical system parameters,

  1. Set the collision detection method of related objects to: CountlessDynamic;
  2. In the Physics column of ProjectSettings, turn on Enable Adaptive Force and increase Default Solver Iterations

  3. Limit the maximum magnetic force

  4. Reduce the collision size of related objects

Writing a bug is a problem that occurred when I was dealing with it, and then I asked the original author, and the original author informed me. grateful! ! ! ! ! ! ! !

Guess you like

Origin blog.csdn.net/chu19970426/article/details/104705228