强大的程序腿效果




程序脚完全使用算法完成,没有复杂的物理运算

3D蜘蛛脚算法

    public class SpiderProceduralAnimation : MonoBehaviour{public Transform[] legTargets;public float stepSize = 0.15f;public int smoothness = 8;public float stepHeight = 0.15f;public float sphereCastRadius = 0.125f;public bool bodyOrientation = true;public float raycastRange = 1.5f;private Vector3[] defaultLegPositions;private Vector3[] lastLegPositions;private Vector3 lastBodyUp;private bool[] legMoving;private int nbLegs;private Vector3 velocity;private Vector3 lastVelocity;private Vector3 lastBodyPos;private float velocityMultiplier = 15f;Vector3[] MatchToSurfaceFromAbove(Vector3 point, float halfRange, Vector3 up){Vector3[] res = new Vector3[2];res[1] = Vector3.zero;RaycastHit hit;Ray ray = new Ray(point + halfRange * up / 2f, -up);if (Physics.SphereCast(ray, sphereCastRadius, out hit, 2f * halfRange)){res[0] = hit.point;res[1] = hit.normal;}else{res[0] = point;}return res;}void Start(){lastBodyUp = transform.up;nbLegs = legTargets.Length;defaultLegPositions = new Vector3[nbLegs];lastLegPositions = new Vector3[nbLegs];legMoving = new bool[nbLegs];for (int i = 0; i < nbLegs; ++i){defaultLegPositions[i] = legTargets[i].localPosition;lastLegPositions[i] = legTargets[i].position;legMoving[i] = false;}lastBodyPos = transform.position;}IEnumerator PerformStep(int index, Vector3 targetPoint){Vector3 startPos = lastLegPositions[index];for (int i = 1; i <= smoothness; ++i){legTargets[index].position = Vector3.Lerp(startPos, targetPoint, i / (float)(smoothness + 1f));legTargets[index].position += transform.up * Mathf.Sin(i / (float)(smoothness + 1f) * Mathf.PI) * stepHeight;yield return new WaitForFixedUpdate();}legTargets[index].position = targetPoint;lastLegPositions[index] = legTargets[index].position;legMoving[0] = false;}void FixedUpdate(){velocity = transform.position - lastBodyPos;velocity = (velocity + smoothness * lastVelocity) / (smoothness + 1f);if (velocity.magnitude < 0.000025f)velocity = lastVelocity;elselastVelocity = velocity;Vector3[] desiredPositions = new Vector3[nbLegs];int indexToMove = -1;float maxDistance = stepSize;for (int i = 0; i < nbLegs; ++i){desiredPositions[i] = transform.TransformPoint(defaultLegPositions[i]);float distance = Vector3.ProjectOnPlane(desiredPositions[i] + velocity * velocityMultiplier - lastLegPositions[i], transform.up).magnitude;if (distance > maxDistance){maxDistance = distance;indexToMove = i;}}for (int i = 0; i < nbLegs; ++i)if (i != indexToMove)legTargets[i].position = lastLegPositions[i];if (indexToMove != -1 && !legMoving[0]){Vector3 targetPoint = desiredPositions[indexToMove] + Mathf.Clamp(velocity.magnitude * velocityMultiplier, 0.0f, 1.5f) * (desiredPositions[indexToMove] - legTargets[indexToMove].position) + velocity * velocityMultiplier;Vector3[] positionAndNormalFwd = MatchToSurfaceFromAbove(targetPoint + velocity * velocityMultiplier, raycastRange, (transform.parent.up - velocity * 100).normalized);Vector3[] positionAndNormalBwd = MatchToSurfaceFromAbove(targetPoint + velocity * velocityMultiplier, raycastRange * (1f + velocity.magnitude), (transform.parent.up + velocity * 75).normalized);legMoving[0] = true;if (positionAndNormalFwd[1] == Vector3.zero){StartCoroutine(PerformStep(indexToMove, positionAndNormalBwd[0]));}else{StartCoroutine(PerformStep(indexToMove, positionAndNormalFwd[0]));}}lastBodyPos = transform.position;if (nbLegs > 3 && bodyOrientation){Vector3 v1 = legTargets[0].position - legTargets[1].position;Vector3 v2 = legTargets[2].position - legTargets[3].position;Vector3 normal = Vector3.Cross(v1, v2).normalized;Vector3 up = Vector3.Lerp(lastBodyUp, normal, 1f / (float)(smoothness + 1));transform.up = up;transform.rotation = Quaternion.LookRotation(transform.parent.forward, up);lastBodyUp = transform.up;}}private void OnDrawGizmosSelected(){for (int i = 0; i < nbLegs; ++i){Gizmos.color = Color.red;Gizmos.DrawWireSphere(legTargets[i].position, 0.05f);Gizmos.color = Color.green;Gizmos.DrawWireSphere(transform.TransformPoint(defaultLegPositions[i]), stepSize);}}}

2D蜘蛛脚算法

    public class SpiderProceduralAnimation : MonoBehaviour{public Transform[] legTargets;public float stepSize = 0.15f;public int smoothness = 8;public float stepHeight = 0.15f;public bool bodyOrientation = true;public float raycastRange = 1.5f;private Vector2[] defaultLegPositions;private Vector2[] lastLegPositions;private Vector2 lastBodyUp;private bool[] legMoving;private int nbLegs;private Vector2 velocity;private Vector2 lastVelocity;private Vector2 lastBodyPos;private float velocityMultiplier = 7f;Vector2[] MatchToSurfaceFromAbove(Vector2 point, float halfRange, Vector2 up){Vector2[] res = new Vector2[2];res[1] = Vector3.zero;RaycastHit2D hit;hit = Physics2D.Raycast(point + halfRange * up / 2f, -up, 2f * halfRange);Debug.DrawRay(point + halfRange * up / 2f, -up * 2f * halfRange, Color.red, smoothness * Time.deltaTime);if (hit.collider){res[0] = hit.point;res[1] = hit.normal;}else{res[0] = point;}return res;}void Start(){lastBodyUp = transform.up;nbLegs = legTargets.Length;defaultLegPositions = new Vector2[nbLegs];lastLegPositions = new Vector2[nbLegs];legMoving = new bool[nbLegs];for (int i = 0; i < nbLegs; ++i){defaultLegPositions[i] = legTargets[i].localPosition;lastLegPositions[i] = legTargets[i].position;legMoving[i] = false;}lastBodyPos = transform.position;}IEnumerator PerformStep(int index, Vector3 targetPoint){Vector3 startPos = lastLegPositions[index];for (int i = 1; i <= smoothness; ++i){legTargets[index].position = Vector3.Lerp(startPos, targetPoint, i / (float)(smoothness + 1f));legTargets[index].position += transform.up * Mathf.Sin(i / (float)(smoothness + 1f) * Mathf.PI) * stepHeight;yield return new WaitForFixedUpdate();}legTargets[index].position = targetPoint;lastLegPositions[index] = legTargets[index].position;legMoving[0] = false;}void FixedUpdate(){velocity = (Vector2)transform.position - lastBodyPos;velocity = (velocity + smoothness * lastVelocity) / (smoothness + 1f);if (velocity.magnitude < 0.000025f)velocity = lastVelocity;elselastVelocity = velocity;Vector2[] desiredPositions = new Vector2[nbLegs];int indexToMove = -1;float maxDistance = stepSize;for (int i = 0; i < nbLegs; ++i){desiredPositions[i] = transform.TransformPoint(defaultLegPositions[i]);float distance = Vector3.ProjectOnPlane(desiredPositions[i] + velocity * velocityMultiplier - lastLegPositions[i], transform.up).magnitude;if (distance > maxDistance){maxDistance = distance;indexToMove = i;}}for (int i = 0; i < nbLegs; ++i)if (i != indexToMove)legTargets[i].position = lastLegPositions[i];if (indexToMove != -1 && !legMoving[0]){Vector2 targetPoint = desiredPositions[indexToMove] + Mathf.Clamp(velocity.magnitude * velocityMultiplier, 0.0f, 1.5f) * (desiredPositions[indexToMove] -(Vector2)legTargets[indexToMove].position) + velocity * velocityMultiplier;Vector2[] positionAndNormalFwd = MatchToSurfaceFromAbove(targetPoint + velocity * velocityMultiplier, raycastRange,((Vector2)transform.parent.up - velocity * 10).normalized);Vector2[] positionAndNormalBwd = MatchToSurfaceFromAbove(targetPoint + velocity * velocityMultiplier, raycastRange * (1f + velocity.magnitude),((Vector2)transform.parent.up + velocity * 10).normalized);legMoving[0] = true;if (positionAndNormalFwd[1] == Vector2.zero){StartCoroutine(PerformStep(indexToMove, positionAndNormalBwd[0]));}else{StartCoroutine(PerformStep(indexToMove, positionAndNormalFwd[0]));}}lastBodyPos = transform.position;if (nbLegs > 1 && bodyOrientation){Vector2 v1 = (legTargets[1].position - legTargets[0].position).normalized;Vector3 v2 = Vector3.back;Vector3 normal = Vector3.Cross(v1, v2).normalized;Vector3 up = Vector3.Lerp(lastBodyUp, normal, 1f / (float)(smoothness + 1));transform.up = up;transform.rotation = Quaternion.LookRotation(transform.parent.forward, up);lastBodyUp = transform.up;}}private void OnDrawGizmosSelected(){for (int i = 0; i < nbLegs; ++i){Gizmos.color = Color.red;Gizmos.DrawWireSphere(legTargets[i].position, 0.05f);Gizmos.color = Color.green;Gizmos.DrawWireSphere(transform.TransformPoint(defaultLegPositions[i]), stepSize);}}}

人物程序动画算法

public class ProceduralAnimation : MonoBehaviour
{/* Some useful functions we may need */static Vector3[] CastOnSurface(Vector3 point, float halfRange, Vector3 up){Vector3[] res = new Vector3[2];RaycastHit hit;Ray ray = new Ray(new Vector3(point.x, point.y + halfRange, point.z), -up);if (Physics.Raycast(ray, out hit, 2f * halfRange)){res[0] = hit.point;res[1] = hit.normal;}else{res[0] = point;}return res;}/*************************************/public Transform leftFootTarget;public Transform rightFootTarget;public Transform leftFootTargetRig;public Transform rightFootTargetRig;public Transform pivot;public Transform scaler;public float smoothness = 2f;public float stepHeight = 0.2f;public float stepLength = 1f;public float angularSpeed = 0.1f;public float velocityMultiplier = 80f;public float bounceAmplitude = 0.05f;public bool running = false;private Vector3 initLeftFootPos;private Vector3 initRightFootPos;private Vector3 lastLeftFootPos;private Vector3 lastRightFootPos;private Vector3 lastBodyPos;private Vector3 initBodyPos;private Vector3 velocity;private Vector3 lastVelocity;// Start is called before the first frame updatevoid Start(){initLeftFootPos = leftFootTarget.localPosition;initRightFootPos = rightFootTarget.localPosition;lastLeftFootPos = leftFootTarget.position;lastRightFootPos = rightFootTarget.position;lastBodyPos = transform.position;initBodyPos = transform.localPosition;}// Update is called once per framevoid FixedUpdate(){velocity = transform.position - lastBodyPos;velocity *= velocityMultiplier;velocity = (velocity + smoothness * lastVelocity) / (smoothness + 1f);if (velocity.magnitude < 0.000025f * velocityMultiplier)velocity = lastVelocity;lastVelocity = velocity;int sign = (Vector3.Dot(velocity.normalized, transform.forward) < 0 ? -1 : 1);scaler.localScale = new Vector3(scaler.localScale.x, stepHeight * 2f * velocity.magnitude, stepLength * velocity.magnitude);scaler.rotation = Quaternion.LookRotation(sign * velocity.normalized, Vector3.up);pivot.Rotate(Vector3.right, sign * angularSpeed, Space.Self);Vector3 desiredPositionLeft = leftFootTarget.position;Vector3 desiredPositionRight = rightFootTarget.position;Vector3[] posNormLeft = CastOnSurface(desiredPositionLeft, 2f, Vector3.up);if (posNormLeft[0].y > desiredPositionLeft.y){leftFootTargetRig.position = posNormLeft[0];}else{leftFootTargetRig.position = desiredPositionLeft;}if (posNormLeft[1] != Vector3.zero){leftFootTargetRig.rotation = Quaternion.LookRotation(sign * velocity.normalized, posNormLeft[1]);}Vector3[] posNormRight = CastOnSurface(desiredPositionRight, 2f, Vector3.up);if (posNormRight[0].y > desiredPositionRight.y){rightFootTargetRig.position = posNormRight[0];}else{rightFootTargetRig.position = desiredPositionRight;}if(posNormRight[1] != Vector3.zero){rightFootTargetRig.rotation = Quaternion.LookRotation(sign * velocity.normalized, posNormRight[1]);}lastLeftFootPos = leftFootTargetRig.position;lastRightFootPos = rightFootTargetRig.position;float feetDistance = Mathf.Clamp01(Mathf.Abs(leftFootTargetRig.localPosition.z - rightFootTargetRig.localPosition.z) / (stepLength / 4f));float heightReduction = (running ? Mathf.Clamp01(velocity.magnitude) * bounceAmplitude - bounceAmplitude * Mathf.Clamp(velocity.magnitude, 0f, 10f) * feetDistance : bounceAmplitude * Mathf.Clamp(velocity.magnitude, 0f, 10f) * feetDistance);transform.localPosition = initBodyPos - heightReduction * Vector3.up;scaler.localPosition = new Vector3(0f, heightReduction, 0f);lastBodyPos = transform.position;}private void OnDrawGizmosSelected(){Gizmos.DrawWireSphere(leftFootTarget.position, 0.2f);Gizmos.DrawWireSphere(rightFootTarget.position, 0.2f);}
}
哇塞这么多代码,头晕,搞不明白,看不太懂

没事的! demo来啦~
点击

Unity 程序动画 2D,3D程序蜘蛛脚,人物程序性动画相关推荐

  1. 前端 css3动画2D|3D

    css3动画&2D|3D 一.css3的transform属性 2d坐标轴(图示) x轴:水平,向右为正,向左为负 y轴:垂直,向下为正,向上为负 2d转换的方法 1.2D变形:平移.旋转.缩 ...

  2. CSS3动画(2D/3D转换、过渡、动画和多列)

    [index.html] <!DOCTYPE html> <html lang="en"> <head><meta charset=&qu ...

  3. Unity ShaderLab: 2D/3D Wave Flag Shader(飘动旗帜)的实现

    个人实现的第一个在实际项目中使用的shader. 2D Wave Flag Shader 效果图: Shader "Custom/WaveFlag2D" {Properties { ...

  4. 打开摄像头,2D插画实时变动画,中国程序媛出品,Demo在线可玩

    鱼羊 发自 凹非寺 量子位 报道 | 公众号 QbitAI 画一只狸(jian)克(shang),并让它拍摄一个「催款」的特写,需要几步? 只需要给狸克安上骨架,再把导出的SVG文件拖进浏览器里,就齐 ...

  5. 《Unity 3D 游戏开发技术详解与典型案例》——1.3节第一个Unity 3D程序

    本节书摘来自异步社区<Unity 3D 游戏开发技术详解与典型案例>一书中的第1章,第1.3节第一个Unity 3D程序,作者 吴亚峰 , 于复兴,更多章节内容可以访问云栖社区" ...

  6. 千寻位置 开发demo_打开摄像头,2D插画实时变动画,中国程序媛出品,Demo在线可玩...

    鱼羊 发自 凹非寺 量子位 报道 | 公众号 QbitAI 画一只狸(jian)克(shang),并让它拍摄一个「催款」的特写,需要几步? 只需要给狸克安上骨架,再把导出的SVG文件拖进浏览器里,就齐 ...

  7. Unity Editor - 在编辑器模式下执行exe程序、打开文件、定位脚本行

    执行exe程序.打开文件 当我们想在Unity 编辑器下 通过exe程序打开指定脚本时我们可以调用以下API 这里我是通过vscode 打开 lua 脚本 并定位到具体某一行. static void ...

  8. 2022-05-14 Unity核心7——2D动画

    文章目录 一.序列帧动画 二.骨骼动画 -- 2D Animation 三.反向动力学 IK 四.换装 五.骨骼动画 -- Spine 一.序列帧动画 (一)什么是序列帧动画 ​ 我们最常见的序列帧动 ...

  9. Unity安卓游戏开发:打造7款2D 3D游戏 Unity Android Game Development : Build 7 2D 3D Games

    流派:电子学习| MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz 语言:英语+中英文字幕(根据原英文字幕机译更准确) |大小:15.4 GB |时长:32h 55m Un ...

最新文章

  1. [转载]Surging 分布式微服务框架使用入门
  2. qt c语言程序运行时间,c – 在Qt中计时事件的最佳方法
  3. 利用angular结合translate为项目实现国际化
  4. 使用gin和gorm框架完成的bubble小清单项目
  5. the vm session was closed before any attempt to power it on
  6. Android开发之shape画圆环的方法
  7. 回想四叉树LOD地形(上)
  8. 2018-2019-2 20165234 《网络对抗技术》 Exp2 后门原理与实践
  9. windows上通过vnc连接虚拟机中linux系统
  10. PDF Explained(翻译)第一章 简介
  11. C++课后作业 10.教材习题7_6:哺乳动物类Mammal派生出狗类Dog
  12. SMCJ系列TVS瞬态抑制二极管型号参数表
  13. Nat Chem Biol | 李大力/宋高洁/赵永祥合作开发“精准安全”的腺嘌呤碱基编辑器ABE9...
  14. 少年,我看你骨骼精奇,见与你有缘,这套算法赠你
  15. 最新android版本叫什么,Android版本今年将大更新,迈入10.0时代,新特性曝光
  16. 计算机操作知识试题及答案,2016计算机信息技术操作考试题及答案
  17. 基于Unity尝试唇同步/LipSync/OVRLipSync(附Demo及源码)
  18. Linux 集群技术
  19. c语言-大小顺序排列
  20. Linux快捷键汇总(持续更新)

热门文章

  1. Navicat使用SSH隧道连接MySQL
  2. 58同城徐振华:58同城分布式存储架构
  3. GRBL V1.1f源码中文注解--GCode篇
  4. 微信小程序for循环遍历数组解决办法
  5. 二十五、SQL 数据分析实战(9个中等难度的SQL题目)
  6. HTML中Pre标签
  7. 乐观锁、悲观锁和公平、非公平
  8. 张东健高小英奢侈育儿 网友表示不理解
  9. 微信小程序中生成二维码工具:weapp.qrcode.js
  10. md语法|LaTex数学公式