写在前面:这个角色动画主要使用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);//主角以速度*时间进行移动 }
注:转载请注明出处
时间: 2024-10-10 14:23:29