zoukankan      html  css  js  c++  java
  • 【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帧时停(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);//主角以速度*时间进行移动
    }

    注:转载请注明出处

  • 相关阅读:
    灾后重建
    ZYN砍树
    聪聪可可
    GirlCat
    图表控件== 百度 echarts的入门学习
    图表控件的学习===》hightChart 和 Chartjs的使用
    拆分订单===初
    net 的单元测试 初学
    vue js 用nodejs的依赖包 --2016-08-23
    后台框架--HUI 的学习跟使用1
  • 原文地址:https://www.cnblogs.com/ljq66/p/7769187.html
Copyright © 2011-2022 走看看