Unity中Skinned Mesh Renderer Blend Shapes小试

Posted u010019717

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity中Skinned Mesh Renderer Blend Shapes小试相关的知识,希望对你有一定的参考价值。

 

第一个应用:如何使用网格渲染器Blend Shapes Unity制作木棍剥皮

1、 Intro

test222.gif

2、Modeling (Blender)

打开Blender 软件

调整视角

image.png

然后快捷键: Shift+A

添加Mesh : Cylinder

顶点数改为:

image.png

 

Rotate Around X Axis : 快捷键 R+X+90

image.png

 

Scale :Y Axis   : 快捷键  S+Y

image.png

进入Edit Mode  :   快捷键  Tab

 

Add more Loops :  快捷键   Ctrl + R   然后改变鼠标的滚轮: image.png    就会看到横向线的变化。

下图中横向线都是新增的 。

image.png    -> image.png

 

Right click to undo movements

image.png

 

Exit Edit  Mode  :   快捷键  Tab

 

 

增加Shape Keys

image.png

image.png

 

 

image.png

进入Edit Mode然后      ,Alt + 横线选中, 然后快捷键 S + 0    , 一个关键帧就完成了。

image.png

重复n次把所有横线都增加key

image.png

 

 

然后点击File 导出 FBX 文件 。

然后导入Unity工程中。

3、 Setup scene

创建空对象挂点, Wood Holder, Wood   , 然后拖拽模型挂上

image.png

然后调整模型的旋转,也可以看到在Blender中添加的 Shape keys 在Unity中有数据, 可以在Inspector中改变key的值查看scene中模型的变化。

image.png

 

替换成更像木头的材质:  wood  

image.png

 

场景中需要放另外的物体: 刻刀 Knife , 有碰撞体跟刚体(限制运动方向等参数设置),与控制脚本Knife.cs

image.png

 

4、Wood Rotation (DoTween)

添加第一个脚本 Wood.cs  让木头先旋转

 

image.png

using UnityEngine ;
using DG.Tweening ;

public class Wood : MonoBehaviour {
   [SerializeField] private SkinnedMeshRenderer skinnedMeshRenderer ;
   [SerializeField] private Transform woodTransform ;
   [SerializeField] private Vector3 rotationVector ;
   [SerializeField] private float rotationDuration ;

   private void Start () {
      woodTransform
         .DOLocalRotate (rotationVector, rotationDuration, RotateMode.FastBeyond360)
         .SetLoops (-1, LoopType.Restart)
         .SetEase (Ease.Linear) ;
   }

   public void Hit (int keyIndex, float damage) {
      float colliderHeight = 2.39705f ;
      //Skinned mesh renderer key's value is clamped between 0 & 100
      float newWeight = skinnedMeshRenderer.GetBlendShapeWeight (keyIndex) + damage * (100f / colliderHeight) ;
      skinnedMeshRenderer.SetBlendShapeWeight (keyIndex, newWeight) ;
   }
}

运行时就会旋转了。

 

5、 Knife Movement

添加脚本 Knife.cs   移动刀片

using UnityEngine ;

public class Knife : MonoBehaviour {
   [SerializeField] private float movementSpeed ;
   [SerializeField] private float hitDamage ;
   [SerializeField] private Wood wood ;

   [SerializeField] private ParticleSystem woodFx ;

   private ParticleSystem.EmissionModule woodFxEmission ;

   private Rigidbody knifeRb ;
   private Vector3 movementVector ;
   private bool isMoving = false ;

   private void Start () {
      knifeRb = GetComponent<Rigidbody> () ;

      woodFxEmission = woodFx.emission ;
   }

   private void Update () {
      isMoving = Input.GetMouseButton (0) ;

      if (isMoving)
         movementVector = new Vector3 (Input.GetAxis ("Mouse X"), Input.GetAxis ("Mouse Y"), 0f) * movementSpeed * Time.deltaTime ;
   }

   private void FixedUpdate () {
      if (isMoving)
         knifeRb.position += movementVector ;
   }

   private void OnCollisionExit (Collision collision) {
      woodFxEmission.enabled = false ;
   }

   private void OnCollisionStay (Collision collision) {
      Coll coll = collision.collider.GetComponent <Coll> () ;
      if (coll != null) {
         // hit Collider:
         woodFxEmission.enabled = true ;
         woodFx.transform.position = collision.contacts [ 0 ].point ;

         coll.HitCollider (hitDamage) ;
         wood.Hit (coll.index, hitDamage) ;
      }
   }
}

 

6、Colliders

 

添加碰撞体:

image.png

先调整参数,这样可以确定每个key的位置

image.png

image.png

为每个碰撞体添加脚本 Coll.cs  

using UnityEngine ;

public class Coll : MonoBehaviour {
   public int index ;

   BoxCollider boxCollider ;

   private void Awake () {
      boxCollider = GetComponent<BoxCollider> () ;
      index = transform.GetSiblingIndex () ;
   }

   public void HitCollider (float damage) {
      // Resize the collider's height(Y) depends on "damage" 
      if (boxCollider.size.y - damage > 0.0f)
         boxCollider.size = new Vector3 (boxCollider.size.x, boxCollider.size.y - damage, boxCollider.size.z) ;
      else
         Destroy (this) ; // Remove Coll Component from this gameobject
   }
}

 

7、Wood Deformation (Skinned Mesh Renderer)

Wood.cs  中     更改指定key的权重来达到木头的削皮

   public void Hit (int keyIndex, float damage) {
      float colliderHeight = 2.39705f ;  // 编辑器时碰撞体的size的y值
      //Skinned mesh renderer key's value is clamped between 0 & 100
      float newWeight = skinnedMeshRenderer.GetBlendShapeWeight (keyIndex) + damage * (100f / colliderHeight) ;
      skinnedMeshRenderer.SetBlendShapeWeight (keyIndex, newWeight) ;
   }

Knife.cs 中   削刀跟key碰撞体 碰撞就改变指定的key的权重

   private void OnCollisionExit (Collision collision) {
      woodFxEmission.enabled = false ;
   }

   private void OnCollisionStay (Collision collision) {
      Coll coll = collision.collider.GetComponent <Coll> () ;
      if (coll != null) {
         // hit Collider:
         woodFxEmission.enabled = true ;
         woodFx.transform.position = collision.contacts [ 0 ].point ;

         coll.HitCollider (hitDamage) ;
         wood.Hit (coll.index, hitDamage) ;
      }
   }

 

 

8、Wood Fx (Particle System)

这个就没什么可说的,特效一直都在,只是在碰撞的时候开启particle system,同时改变特效的位置。脱离碰撞就关闭。

 

 

 

第二个应用:树的出现动画

image.png

test222.gif

 

image.png

添加一个cube:

image.png

然后添加水平跟垂直的边缘循环。

image.png

 

然后增加  Shape Keys  : Base ,  key 1   把Cube 调整成树的形状。

 

image.png

编辑完  可以通过改变 Value 条来看效果,也有Misc参数可以调整。

就是从cube   key成这样:

image.png

然后退出编辑模式,  为Cube 添加简单的纹理

image.png

 

然后将文件从Blender中导出 .fbx文件, 导入到Unity中

托转到场景中可是改变值看看效果:

image.png

image.png

添加如下控制脚本 ,作为数目的出生动画 :

image.png

 

 

 

 

 

以上是关于Unity中Skinned Mesh Renderer Blend Shapes小试的主要内容,如果未能解决你的问题,请参考以下文章

Unity中Skinned Mesh Renderer Blend Shapes小试

Unity中Skinned Mesh Renderer Blend Shapes小试

如何创建自己的 Raycast 组件,它不需要碰撞器,但在 C# Unity3D 中支持 Skinned Mesh Renderer?

Unity3d VFX 采用skinned mesh sampling(蒙皮采样)发射粒子效果时fbx模型是否优化(Optimized)带来的问题记录

Runtime Mesh Baker v1.1.3 中文手册(自己参考)

Unity3d bounds包围盒 和collider碰撞器区别