unity 利用2d toolkit 实现按帧改变碰撞监测范围
2015-12-10 00:01
691 查看
自己在做动作类游戏的时候,碰到一个问题,在攻击的时候按帧播放,每一帧的攻击范围都是不同的,怎样才能实现每帧都能够检测图片对应的碰撞范围?
在网上找了很多资料,有好几种解决方案,其中包括射线检测等方法,虽然这些方法代码实现方便而且效率比较高,但是检测不够精确,而且局限性较大。
2d toolkit有很强大的功能,但是网上资料太少了,我也没找到这样的帖子来实现按帧改变碰撞监测范围。
创建一个Sprite With Animation,该物体包含Mesh Filter、Mesh Renderer、Mesh Collider、Tk 2d Sprite、Tk 2d Sprite Animator等组件。其中Mesh Collider是网格碰撞器,Tk 2d Sprite和Tk 2d Sprite Animator是2d toolkit的类,分别控制一个Clip(包含一定数量的图片)管理类和众多Clip组成的管理类。
控制一个动画的流程:
在Sprite Collection中为每帧图片绘制碰撞体积的后,然后添加到Sprite Animation中组成一个Clip,并在Tk 2d Sprite、Tk 2d Sprite Animator中选择它们。
用过2d toolkit的人应该都知道上面的流程,但是你会很奇怪在Inspector界面调节Tk 2d Sprite中的Sprite选项时Scene窗口的碰撞范围会改变,而在程序运行的时候并没有随着Sprite的切换而切换对应的碰撞范围,它只停留在初始Sprite的碰撞范围。
这个问题困扰了我很久,我也是刚接触unity,并不怎么搞。
今天我瞎搞,看了2d toolkit自带的类tk2dSprite、tk2BaseSprite、tk2dSpriteDefinition等这几类
tk2dSprite继承了tk2BaseSprite,并且包含了一组tk2dSpriteDefinition,tk2dSpriteDefinition相当于每一张的图片。
在tk2BaseSprite类中有个函数CreateCollider(),该函数实现了创建碰撞器,当其碰撞器类型为tk2dSpriteDefinition.ColliderType.Mesh,即网格的时候,则执行下面代码:
对应的部分变量的定义
如果我们动态的对Sprite With Animation中的Mesh Collider中的shareMesh进行初始化进行覆盖,那不就可以实现播放哪张图片的时候使用它对应的碰撞范围了?
结果成功了。看下面代码:
以上简单的实现了这个功能,将它挂在对应的Sprite With Animation上就可以了,代码只描述了功能,比较简陋,具体的优化自己去实现吧,少年!!
在网上找了很多资料,有好几种解决方案,其中包括射线检测等方法,虽然这些方法代码实现方便而且效率比较高,但是检测不够精确,而且局限性较大。
2d toolkit有很强大的功能,但是网上资料太少了,我也没找到这样的帖子来实现按帧改变碰撞监测范围。
创建一个Sprite With Animation,该物体包含Mesh Filter、Mesh Renderer、Mesh Collider、Tk 2d Sprite、Tk 2d Sprite Animator等组件。其中Mesh Collider是网格碰撞器,Tk 2d Sprite和Tk 2d Sprite Animator是2d toolkit的类,分别控制一个Clip(包含一定数量的图片)管理类和众多Clip组成的管理类。
控制一个动画的流程:
在Sprite Collection中为每帧图片绘制碰撞体积的后,然后添加到Sprite Animation中组成一个Clip,并在Tk 2d Sprite、Tk 2d Sprite Animator中选择它们。
用过2d toolkit的人应该都知道上面的流程,但是你会很奇怪在Inspector界面调节Tk 2d Sprite中的Sprite选项时Scene窗口的碰撞范围会改变,而在程序运行的时候并没有随着Sprite的切换而切换对应的碰撞范围,它只停留在初始Sprite的碰撞范围。
这个问题困扰了我很久,我也是刚接触unity,并不怎么搞。
今天我瞎搞,看了2d toolkit自带的类tk2dSprite、tk2BaseSprite、tk2dSpriteDefinition等这几类
tk2dSprite继承了tk2BaseSprite,并且包含了一组tk2dSpriteDefinition,tk2dSpriteDefinition相当于每一张的图片。
在tk2BaseSprite类中有个函数CreateCollider(),该函数实现了创建碰撞器,当其碰撞器类型为tk2dSpriteDefinition.ColliderType.Mesh,即网格的时候,则执行下面代码:
else if (sprite.colliderType == tk2dSpriteDefinition.ColliderType.Mesh && boxCollider == null) { // this should not be updated again (apart from scale changes in the editor, where we force regeneration of colliders) if (meshCollider == null) meshCollider = gameObject.AddComponent<MeshCollider>(); if (meshColliderMesh == null) meshColliderMesh = new Mesh(); meshColliderMesh.Clear(); meshColliderPositions = new Vector3[sprite.colliderVertices.Length]; for (int i = 0; i < meshColliderPositions.Length; ++i) meshColliderPositions[i] = new Vector3(sprite.colliderVertices[i].x * _scale.x, sprite.colliderVertices[i].y * _scale.y, sprite.colliderVertices[i].z * _scale.z); meshColliderMesh.vertices = meshColliderPositions; float s = _scale.x * _scale.y * _scale.z; meshColliderMesh.triangles = (s >= 0.0f)?sprite.colliderIndicesFwd:sprite.colliderIndicesBack; meshCollider.sharedMesh = meshColliderMesh; meshCollider.convex = sprite.colliderConvex; meshCollider.smoothSphereCollisions = sprite.colliderSmoothSphereCollisions; // this is required so our mesh pivot is at the right point if (rigidbody) rigidbody.centerOfMass = Vector3.zero; }
对应的部分变量的定义
public MeshCollider meshCollider = null; public Vector3[] meshColliderPositions = null; public Mesh meshColliderMesh = null;其中该代码利用tk2dSpriteDefinition(每一张图片一些定义)初始化构造了meshColliderMesh,即每一张图片的tk2dSpriteDefinition都能初始化相应的网格。
如果我们动态的对Sprite With Animation中的Mesh Collider中的shareMesh进行初始化进行覆盖,那不就可以实现播放哪张图片的时候使用它对应的碰撞范围了?
结果成功了。看下面代码:
using UnityEngine; using System.Collections; public class test : MonoBehaviour { private tk2dSprite roleSprite; // Use this for initialization void Start () { roleSprite = GetComponent<tk2dSprite>(); if (roleSprite == null) Debug.Log("oh noo!"); } // Update is called once per frame void Update () { { Vector3[] meshColliderPositions = null; Mesh meshColliderMesh = null; if (meshColliderMesh == null) meshColliderMesh = new Mesh(); meshColliderMesh.Clear(); meshColliderPositions = new Vector3[roleSprite.CurrentSprite.colliderVertices.Length]; for (int i = 0; i < meshColliderPositions.Length; ++i) meshColliderPositions[i] = new Vector3(roleSprite.CurrentSprite.colliderVertices[i].x * roleSprite.scale.x, roleSprite.CurrentSprite.colliderVertices[i].y * roleSprite.scale.y, roleSprite.CurrentSprite.colliderVertices[i].z * roleSprite.scale.z); meshColliderMesh.vertices = meshColliderPositions; float s = roleSprite.scale.x * roleSprite.scale.y * roleSprite.scale.z; meshColliderMesh.triangles = (s >= 0.0f) ? roleSprite.CurrentSprite.colliderIndicesFwd : roleSprite.CurrentSprite.colliderIndicesBack; GetComponent<MeshCollider>().sharedMesh = meshColliderMesh; } } }
以上简单的实现了这个功能,将它挂在对应的Sprite With Animation上就可以了,代码只描述了功能,比较简陋,具体的优化自己去实现吧,少年!!
相关文章推荐
- Android平台Unity所有声音从听筒播放
- Unity脚本在层级面板中的执行顺序测试2
- Unity3D-Unity Remote
- Unity协程(Coroutine)原理深入辨析
- 今天开始使用unity 5.3 进行学习编程
- Unity3D抗锯齿设置
- Unity3D脚本--真实1
- Unity 协程与线程区别
- 【Unity Shader】结合Projector和Rendertexture实现实时阴影
- Unity3d的电脑AI以及自动寻路
- Unity3D 如何图形问题修正旋转模型已导入?
- unity制作体积光实现丁达尔效应
- unity3d调用win32打开对话框
- Unity3D 学习笔记
- Unity5中lightmap的坑
- raknet for unity3d手机版的编译方法
- 基于Unity3D的google cardboard开发
- 解决Unity3D离线HTML文件打开缓慢问题
- Unity3D ----- 生命周期
- 跟我从零基础学习Unity3D开发--资源打包篇(AssetBundle)