【Salvation】——人物角色动画实现
写在前面:这个角色动画主要使用JavaScript编写脚本,在Unity3D游戏引擎的环境中实现。

| 一、显示角色并实现镜像效果 |
1、显示贴图:
create→cube→修改名称为player,位置归0,将sprite换掉cube
- 把Idle静止贴图,拖放到player的属性编辑器中,把背景去掉,要透明的:shader - unlit/Transparent
- 把Run动画序列,拖放到player的属性编辑器中,把背景去掉,要透明的:shader-Unlit/Transparent
说明:
通过控制Tilling和Offset来实现角色的镜像效果,当两者都为负值时,角色反向运动。
| Tiling | Offset(偏移) | |
| X | 0.1 | 0.1(第二张)→0为第一张 |
| y | 1 | 0 |
动画脚本:animationController
//animationController:(图片控制功能)
#pragma strict
var lastFrameNo:int=0;
var destroy:boolean=false;//控制销毁不销毁
var direction:boolean=true;//控制人物左右移动的动画,默认true向左跑
var frameNumber:int=3;//设置动画序列帧有多少帧,默认3帧
private var index:int=0;//index的值反映了显示的是第几帧的图片,0为第一张
private var oneTime:boolean=true;
private var frameRate:float=0;//帧速率,10帧,1秒内每一帧占的间隔就是0.1
private var myTime:float=0;
private var myIndex:int=0; function Update () { frameRate=1.0f/frameNumber; if(oneTime){//第一次执行,ture执行动画,false不执行,静止
myTime += Time.deltaTime;//计时开始
myIndex=myTime*(frameNumber-1);//产生一个整数
index=myIndex%frameNumber;//显示第几张图片,index的值从0-9
} if(direction){【关键代码】
//设置Tiling与Offset属性,正,向左跑
renderer.material.mainTextureScale=new Vector2(frameRate,1);
renderer.material.mainTextureOffset=new
Vector2(index*frameRate,0);
}else{
//镜像效果,加负号,向右跑
renderer.material.mainTextureScale=new Vector2(-frameRate,1);
renderer.material.mainTextureOffset=new
Vector2(index*frameRate,0);
}
if(index==frameNumber-1 && destroy ){ Destroy(gameObject);}
//判断是否销毁,destroy变量为true,销毁,为false,不销毁 if(lastFrameNo != 0){//判断最后一帧显示第几帧,为0动画循环播放
if(index==lastFrameNo-1){oneTime=false;}
//不为0设置oneTime为false,动画不执行,这一帧图片静止
}
}
脚本重要实现程序片段,要放在Update函数中,而不是start函数中
原因:start函数志执行一次,而程序后面还需要更新,所以选择放在Update函数中
- Direction后的选项要勾选,向左跑,不勾选会向右跑
- Frame Number 10 :10帧,一序列有10张图片,分10份
- Last Frame No 6 :设置为6帧,动画显示到第6帧时停(0 :设置为0,循环播放跑这个动画)
| 二、检测按键并控制玩家状态 |
创建脚本,并将脚本拖进player的属性编辑器→将所有角色的状态图片在编辑器上,关联到对应位置
动画脚本:playerStateController
//playerStateController(玩家状态控制功能) #pragma strict
var idle:Texture;//引用图片
var run:Texture;
var jump:Texture;
var die:Texture;
var winTexture:Texture2D;
var dieTexture:Texture2D; var gameState:GameState;//定义变量,标识玩家状态 var levelName:String;//定义关卡名字的变量 var soundName:AudioClip;//引用胜利声音
var dieSound:AudioClip;//引用死亡声音 private var myAnimation:animationController;//引用动画控制脚本(组件) private var moveDirection:boolean=true;//定义移动方向 boolean型
private var exit:boolean=false;//定义出口 碰到出口,设置为true
private var youWin:boolean=false;//是否取胜
private var youDie:boolean=false;//是否死亡 function Start () {
youDie=false;
myAnimation=GetComponent("animationController");//取得动画控制组件的
控制(使用)权
} function Update () {
if(Input.GetAxis("Horizontal")>0){//按了D键,正移,向右走
moveDirection=false;//设置移动方向的变量,向右,为false
if(Input.GetButton("Jump")){//检测是否按下空格键
gameState=GameState.jumpRight;//按下了空格键,右跑跳
}
else{gameState=GameState.runRight;//没按空格键,只向右跑
} }else{
if(Input.GetAxis("Horizontal")<0){//按了A键,向左走
moveDirection=true;
if(Input.GetButton("Jump")){检测是否按了空格键
gameState=GameState.jumpLeft;//按了空格键,左跑跳
}else{
gameState=GameState.runLeft;//没按,只向左跑
} }else{//检测既没按A键,也没按D键的时候,按没按空格键
if(Input.GetButton("Jump")){//按了空格键,跳
if(moveDirection){//检测当时的运动方向
gameState=GameState.idleLeftJump;//true,静止左跳
}else{gameState=GameState.idleRightJump;//false,静止右跳
} }else{gameState=GameState.idle;}//没按空格键,静止状态 }
} if(youDie){gameState=GameState.die;}
//youDie为true,播放死亡动画 switch(gameState){//根据gameState的不同值,执行下面的语句
case GameState.idle:
transform.renderer.material.SetTexture("_MainTex",idle);
//更换玩家图片为idle
myAnimation.frameNumber=1;//设置为静止的一帧图片
myAnimation.direction=false;//设置方向变量
//打勾为true,取消为false
break;//执行完这一块后跳出,后面的不执行了 case GameState.runLeft:
transform.renderer.material.SetTexture("_MainTex",run);
//更换玩家图片为run
myAnimation.frameNumber=10;//设置为一序列的10帧图片
myAnimation.direction=true;//设置方向变量,向左跑
break;//跳出 case GameState.runRight:
transform.renderer.material.SetTexture("_MainTex",run);
myAnimation.frameNumber=10;
myAnimation.direction=false;//设置方向变量,向右跑
break; case GameState.jumpLeft:
transform.renderer.material.SetTexture("_MainTex",jump);
myAnimation.frameNumber=11;
myAnimation.direction=true;//设置方向变量,向左跳
break; case GameState.jumpRight:
transform.renderer.material.SetTexture("_MainTex",jump);
myAnimation.frameNumber=11;
myAnimation.direction=false;//设置方向变量,向右跳
break; case GameState.idleRightJump:
transform.renderer.material.SetTexture("_MainTex",jump);
myAnimation.frameNumber=11;
myAnimation.direction=false;//设置方向变量,静止右跳
break; case GameState.idleLeftJump:
transform.renderer.material.SetTexture("_MainTex",jump);
myAnimation.frameNumber=11;
myAnimation.direction=true;//设置方向变量,静止左跳
break; case GameState.celebrate:
transform.renderer.material.SetTexture("_MainTex",celebrate);
myAnimation.frameNumber=11;
myAnimation.direction=false;//设置方向变量,方向向右
myAnimation.lastFrameNo=8;//最后显示的图片是第8帧
break; case GameState.die:
transform.renderer.material.SetTexture("_MainTex",die);
myAnimation.frameNumber=12;
myAnimation.direction=false;//设置方向变量,方向向右
myAnimation.lastFrameNo=11;//最后显示的图片是第11帧
break;
} if(Input.GetButton("Jump")&& youDie){//死亡
transform.position=new Vector3(0,-2,0);//重新设置玩家的位置
transform.collider.enabled=true;//打开玩家的碰撞器
youDie=false;//“已经死了”这个变量,设为false
不再触发死亡这个状态 } } function OnTriggerEnter(other:Collider){//碰撞检测函数 if(other.tag=="monster"){//检测玩家是否碰到了敌人
youDie=true;//设置死亡为true
AudioSource.PlayClipAtPoint(dieSound,Vector3(0,0,-10));
//播放一个死亡的声音
yield WaitForSeconds(0.5);//演示0.5秒
//transform.collider.enabled=false;//关闭玩家的碰撞器
}
}
这里要开发一个新类:游戏状态类
将enum GameState{……}分离出来,把所有状态归在一起,开发一个新的游戏状态类文件→gameState.js
//ameState:(游戏状态类) #pragma strict
enum GameState{
idle,runLeft,runRight,jumpLeft,jumpRight,idleLeftJump,idleRightJump,celebrate,die}
//将所有的玩家游戏状态类分离出来,便于后面的引用
| 三、接收状态并控制角色移动 |
给主角添加角色控制器(组件)——player
Scence →Component→phsics→Chanracter Controller
调整控制器半径大小,让它更符合角色的尺寸 Radius:0.23(左右)
把脚本放在player的属性编辑器里
动画脚本:playerController
//playerController(角色移动控制)
#pragma strict
private var speed:float=2.0;//定义速度
private var jumpspeed:float=4.5;//定义跳跃速度
private var controller:CharacterController;//引用角色控制器(组件)
private var velocity:Vector3=Vector3.zero;//定义速度为三维向量类型
private var gravity:float=20.0;//定义玩家向下运动的重力
private var gameState:GameState;//定义游戏状态的变量,用来接收游戏状态
private var myplayerStateController:playerStateController;
//引用玩家状态控制脚本 function Start () {
myplayerStateController=GetComponent("playerStateController");
//获取玩家状态控制脚本的控制权
controller=GetComponent("CharacterController");
//取得玩家的角色控制器的控制权
} function Update () {
gameState=myplayerStateController.gameState;
//从玩家状态控制脚本中接收玩家当前的游戏状态 if(controller.isGrounded){//判断玩家是否在地面上
(角色控制器底部是否与平面的碰撞器碰撞)
switch(gameState){//检测玩家当前的游戏状态
case GameState.runRight://向右跑
velocity=speed*Vector3(1,0,0);
//速度,X轴的正方向
break;
case GameState.runLeft: //向左跑
velocity=speed*Vector3(-1,0,0);
//速度,X轴的负方向
break;
case GameState.jumpLeft: //左跑跳
velocity=speed*Vector3(-1,jumpspeed,0);
//速度,X轴的负方向,Y轴向上
break;
case GameState.jumpRight://右跑跳
velocity=speed*Vector3(1,jumpspeed,0);
//速度,X轴的正方向,Y轴向上
break;
case GameState.idleLeftJump://静止左跳
velocity=speed*Vector3(0,jumpspeed,0);
//速度,Y轴向上
break; case GameState.idleRightJump://静止右跳
velocity=speed*Vector3(0,jumpspeed,0);
//速度,Y轴向上
break;
case GameState.celebrate://静止
velocity=Vector3.zero;//速度为0
break;
default://其他状态
velocity=Vector3.zero;//速度为0
break; } }else{//如果玩家不再地面上,而在空中 velocity.y -= gravity*Time.deltaTime;
//(y方向的)速度=y方向的速度-重力*时间
(只能往下落,直到y方向的速度为0,落到地面上,重新进行上面的处理)
}
//移动【关键代码】
controller.Move(velocity*Time.deltaTime);//主角以速度*时间进行移动
}
注:转载请注明出处
【Salvation】——人物角色动画实现的更多相关文章
- 时光煮雨 Unity3D实现2D人物动画① UGUI&Native2D序列帧动画
系列目录 [Unity3D基础]让物体动起来①--基于UGUI的鼠标点击移动 [Unity3D基础]让物体动起来②--UGUI鼠标点击逐帧移动 时光煮雨 Unity3D让物体动起来③—UGUI DoT ...
- 2D骨骼动画工具DragonBones的使用教程
怎样用更少的美术成本创造出更生动的动画效果?今天就为大家介绍一套开源的2D骨骼动画框架和工具--DragonBones,它包含了桌面骨骼动画制作工具DragonBonesPro和一套多语言版本的Dra ...
- 【Salvation】——怪物角色动画&主角碰撞死亡动画
写在前面:这个动画功能同样也是使用JavaScript编写脚本,在Unity3D游戏引擎的环境中实现,在怪物的角色动画中,很多与人物相同,这里不再重复. 一.设计敌人 拖一个精英sprite到层次面板 ...
- Unity3D Mecanim 动画系统骨骼动画问题解决方法
http://7dot9.com/2014/08/16/unity3d-mecanim%E5%8A%A8%E7%94%BB%E7%B3%BB%E7%BB%9F%E9%AA%A8%E9%AA%BC%E5 ...
- 关于Unity中Mecanim动画的重定向与动画混合
应用 一个RPG游戏,里面有100种怪物,每种怪物其实都差不多的,行走,跳跃,攻击,难道动画师要调100次动画吗?其实不需要 Unity抽象出人形动画系统,用Unity简化版的骨骼来进行统一的管理,只 ...
- 关于Unity中新版动画系统的使用
Mecanim动画 1:旧版动画系统只能通过代码来控制动画播放,随着动画种类变多,代码复杂度也会增加,同时动画过渡也需要非常繁琐的代码控制,为了让有经验的动画师开发动画,unity推出了针对人物角色的 ...
- 【Salvation】——项目进展&已取得的成果
写在前面:这个项目为原创团体项目,其中美术设计与部分关卡功能为其他成员完成,我负责的部分以角色动画和登录注册为主. 一.游戏美术设计 游戏背景,道具,动物,人物帧动画制作全部完成. 1.人物 2.游戏 ...
- Unity中的动画系统和Timeline(5) Timeline
在前面的动画,都是控制单独的物体,比如说控制一个角色的运动.而Timeline,可以对多个物体实施动画,形成过场动画,或者电影效果.比如,很多赛车游戏比赛开始前都会播放一段开场动画,围绕自己车的几个方 ...
- 动画requestAnimationFrame
前言 在研究canvas的2D pixi.js库的时候,其动画的刷新都用requestAnimationFrame替代了setTimeout 或 setInterval 但是jQuery中还是采用了s ...
随机推荐
- c++ 中的slipt实现
来自 http://www.cnblogs.com/dfcao/p/cpp-FAQ-split.html http://blog.diveinedu.com/%E4%B8%89%E7%A7%8D%E5 ...
- maven学习(十)——maven生命周期以及插件
一.生命周期 1.何为生命周期? Maven生命周期就是为了对所有的构建过程进行抽象和统一,包括项目清理,初始化,编译,打包,测试,部署等几乎所有构建步骤 2.Maven三大生命周期 Maven有三套 ...
- 【bzoj3544】[ONTAK2010]Creative Accounting 前缀和+STL-set
题目描述 给定一个长度为N的数组a和M,求一个区间[l,r],使得$(\sum\limits_{i=l}^{r}{a_i})\ mod\ M$的值最大,求出这个值,注意这里的mod是数学上的mod(即 ...
- BZOJ 4561 [JLoi2016]圆的异或并 ——扫描线
扫描线的应用. 扫描线就是用数据结构维护一个相对的顺序不变,带修改的东西. 通常只用于一次询问的情况. 抽象的看做一条垂直于x轴直线从左向右扫过去. 这道题目要求求出所有圆的异或并. 所以我们可以求出 ...
- Python之面向对象:封装
1.封装的概念 将对象的数据与操作数据的方法相结合,通过方法将对象的数据与实现细节保护起来,就称为封装.外界只能通过对象的方法访问对象,因此封装同时也实现了对象的数据隐藏. 在使用面向对象的封装特性时 ...
- Python之时间:time模块
import time 对于时间,使用最频繁的模块 1.获取当前时间 (1)时间戳 time.time() 时间戳:从1970年1月1日0点开始到现在按秒计算的偏移量 (2)时间元组 time.l ...
- linux之参数实用讲解
<1>linux文件参数 在Windows下是使用 %1 %2 %3 而在Linux下是使用 $1 $2 $3 ------------------- 如: 1.某bat文件 cd ...
- linux安全机制学习【转】
转自:http://blog.csdn.net/qq_20307987/article/details/51307820 曾经一度想学来着,今天看到一个链接,讲的很好,算是写一下加深印象吧 1 栈溢出 ...
- systemd 开机无法启动privoxy
此博客不在更新,我的博客新地址:www.liuquanhao.com ----------------------------------------------------------------- ...
- 【原创】Word2010 清除样式
使用场景 有时候我们在网页上面粘贴一些精华文章或者从去整理别人已经完成的word的时候,会发现它自带的格式,可能并不是我们所理想的格式,所以此时就不得不去重新编辑其格式,但是word里 ...