Unity中作2D藤曼生长效果

参考:https://github.com/dci05049/Verlet-Rope-Unity
使用插件:Dotween

绳子代码修改:

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

public class RopeBridge : MonoBehaviour
{
    public Transform StartPoint;
    public Transform EndPoint;

    private LineRenderer lineRenderer;
    public List<RopeSegment> ropeSegments = new List<RopeSegment>();
    public float ropeSegLen = 0.25f;
    public int segmentLength = 35;
    public float startWidth = 0.1f;
    public float endWidth = 0.1f;
    // Use this for initialization
    void Start()
    {
        this.lineRenderer = this.GetComponent<LineRenderer>();
        Vector3 ropeStartPoint = StartPoint.position;

        for (int i = 0; i < segmentLength; i++)
        {
            this.ropeSegments.Add(new RopeSegment(ropeStartPoint));
            ropeStartPoint.y -= ropeSegLen;
        }
    }

    // Update is called once per frame
    void Update()
    {
        this.DrawRope();
    }

    private void FixedUpdate()
    {
        this.Simulate();
    }

    private void Simulate()
    {
        // SIMULATION
        Vector2 forceGravity = new Vector2(0f, -1f);

        for (int i = 1; i < this.segmentLength; i++)
        {
            RopeSegment firstSegment = this.ropeSegments[i];
            Vector2 velocity = firstSegment.posNow - firstSegment.posOld;
            firstSegment.posOld = firstSegment.posNow;
            firstSegment.posNow += velocity;
            firstSegment.posNow += forceGravity * Time.fixedDeltaTime;
            this.ropeSegments[i] = firstSegment;
        }

        //CONSTRAINTS
        for (int i = 0; i < 50; i++)
        {
            this.ApplyConstraint();
        }
    }

    private void ApplyConstraint()
    {
        //Constrant to First Point 
        RopeSegment firstSegment = this.ropeSegments[0];
        firstSegment.posNow = this.StartPoint.position;
        this.ropeSegments[0] = firstSegment;


        //Constrant to Second Point 
        RopeSegment endSegment = this.ropeSegments[this.ropeSegments.Count - 1];
        endSegment.posNow = this.EndPoint.position;
        this.ropeSegments[this.ropeSegments.Count - 1] = endSegment;

        for (int i = 0; i < this.segmentLength - 1; i++)
        {
            RopeSegment firstSeg = this.ropeSegments[i];
            RopeSegment secondSeg = this.ropeSegments[i + 1];

            float dist = (firstSeg.posNow - secondSeg.posNow).magnitude;
            float error = Mathf.Abs(dist - this.ropeSegLen);
            Vector2 changeDir = Vector2.zero;

            if (dist > ropeSegLen)
            {
                changeDir = (firstSeg.posNow - secondSeg.posNow).normalized;
            }
            else if (dist < ropeSegLen)
            {
                changeDir = (secondSeg.posNow - firstSeg.posNow).normalized;
            }

            Vector2 changeAmount = changeDir * error;
            if (i != 0)
            {
                firstSeg.posNow -= changeAmount * 0.5f;
                this.ropeSegments[i] = firstSeg;
                secondSeg.posNow += changeAmount * 0.5f;
                this.ropeSegments[i + 1] = secondSeg;
            }
            else
            {
                secondSeg.posNow += changeAmount;
                this.ropeSegments[i + 1] = secondSeg;
            }
        }
    }

    private void DrawRope()
    {
        lineRenderer.startWidth = this.startWidth;
        lineRenderer.endWidth = this.endWidth;
        Vector3[] ropePositions = new Vector3[this.segmentLength];
        for (int i = 0; i < this.segmentLength; i++)
        {
            ropePositions[i] = this.ropeSegments[i].posNow;
        }

        lineRenderer.positionCount = ropePositions.Length;
        lineRenderer.SetPositions(ropePositions);
    }

    public struct RopeSegment
    {
        public Vector2 posNow;
        public Vector2 posOld;

        public RopeSegment(Vector2 pos)
        {
            this.posNow = pos;
            this.posOld = pos;
        }
    }
    void OnDrawGizmos()
    {
        DrawBGLine();
    }

    private void DrawBGLine()
    {

#if UNITY_EDITOR
        Gizmos.color = Color.green;
        Gizmos.DrawLine(StartPoint.position, EndPoint.position);

#endif
    }
}

动画代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using System;
using UnityEngine.Events;

public class RopeAnim:MonoBehaviour
{
    Transform parent;
    RopeBridge ropeBridge;
    Vector3 target;
    Tween tween;
    public float percent = 0.5f;
    public UnityEvent OnAnimEnd;
    public float duration=10;
    // Start is called before the first frame update
    void Start()
    {
        ropeBridge = GetComponent<RopeBridge>();
        target = ropeBridge.EndPoint.position;
        ropeBridge.EndPoint.position = ropeBridge.StartPoint.position;
        parent = transform.parent;
        startWidth = ropeBridge.startWidth;
        endwidth = ropeBridge.endWidth;
        InitAnim();
    }
    float startWidth = 0;
    float endwidth = 0;
    public void InitAnim()
    {
        ropeBridge.EndPoint.position = ropeBridge.StartPoint.position;
        ropeBridge.startWidth = 0f;
        ropeBridge.endWidth = 0f;
        if (parent == null){
            for (int i = 0; i < transform.childCount; i++) {
                RopeAnim childAnim = transform.GetChild(i).GetComponent<RopeAnim>();
                if (childAnim != null) {
                    childAnim.InitAnim();
                }
            }
        }
        
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    public void Play()
    {
        //ropeBridge.lineWidth = 0.1f;
        ropeBridge.startWidth = startWidth;
        ropeBridge.endWidth = endwidth;
        ropeBridge.ropeSegLen = 0.01f;
        tween =ropeBridge.EndPoint.DOMove(target, duration).OnComplete(OnComplete).OnUpdate(OnUpdate);
    }

    private void OnUpdate()
    {
        if (parent != null)
        {
            if (parent.GetComponent<RopeBridge>())
            {
                RopeBridge parentBridge = parent.GetComponent<RopeBridge>();
                int NodePoint = (int)(parentBridge.segmentLength * percent);
                if (NodePoint > parentBridge.segmentLength - 1)
                {
                    NodePoint = parentBridge.segmentLength - 1;
                }
                if (NodePoint < 0)
                {
                    NodePoint = 0;
                }
                ropeBridge.StartPoint.position = parentBridge.ropeSegments[NodePoint].posNow;
            }
        }
    }

    private void OnComplete()
    {
        if (OnAnimEnd != null)
        {
            OnAnimEnd.Invoke();
        }
        if (parent != null) {
            ropeBridge.ropeSegLen = 0.05f;
            ropeBridge.EndPoint.DOShakePosition(1, 0.2f, 5, 10).SetLoops(-1).OnUpdate(OnUpdate);
        }
        
    }
    public void Stop()
    {
        tween.Pause();
    }
}

外链图片转存失败(img-Ai1Ae9FG-1563354627480)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值