【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);//主角以速度*时间进行移动
}


注:转载请注明出处

时间: 2024-10-10 14:23:29

【Salvation】——人物角色动画实现的相关文章

2D骨骼动画工具DragonBones的使用教程

怎样用更少的美术成本创造出更生动的动画效果?今天就为大家介绍一套开源的2D骨骼动画框架和工具--DragonBones,它包含了桌面骨骼动画制作工具DragonBonesPro和一套多语言版本的DragonBones骨骼动画库. 下面为大家介绍DragonBones的常用术语和使用方法. 一.DragonBones 2D骨骼动画中的常用术语骨架:骨架Armature,是2D骨骼动画中最常用的名词,一般指的是由很多骨骼组成的一个整体.DragonBones中同时代表一个可以包含动画的角色. 骨骼(

【Salvation】——怪物角色动画&amp;主角碰撞死亡动画

写在前面:这个动画功能同样也是使用JavaScript编写脚本,在Unity3D游戏引擎的环境中实现,在怪物的角色动画中,很多与人物相同,这里不再重复. 一.设计敌人 拖一个精英sprite到层次面板,把名字改为monster 把敌人 10帧的动画 run 拖给敌人 把动画控制脚本 animationController拖给敌人 设置Frame Number:10     Direction:勾选,向左 给敌人添加碰撞器  Box Collider  勾选IsTrigger 调整碰撞器的大小  

关于Unity中新版动画系统的使用

Mecanim动画 1:旧版动画系统只能通过代码来控制动画播放,随着动画种类变多,代码复杂度也会增加,同时动画过渡也需要非常繁琐的代码控制,为了让有经验的动画师开发动画,unity推出了针对人物角色的Mecanim动画系统;2:Mecanim支持运动重定向(Retargeting)功能,即把动画从一个角色模型应用到另一个角色模型;3: Mecanim允许使用"肌肉"来控制不同骨骼的运动范围;觉得某个动画太夸张的时候,可以用"肌肉"来限制一下.4: Mecanim动画

【Salvation】——项目进展&amp;已取得的成果

写在前面:这个项目为原创团体项目,其中美术设计与部分关卡功能为其他成员完成,我负责的部分以角色动画和登录注册为主. 一.游戏美术设计 游戏背景,道具,动物,人物帧动画制作全部完成. 1.人物 2.游戏背景 3.怪物 4.小动物 5.开始剧情 6.开始说明与登录注册 7.结局 二.游戏关卡功能 游戏的三个关卡,难度从低到高,包括角色动画,背景切换等技术功能全部实现. 1.角色动画: 玩家控制的角色,可以通过控制←↑→键,实现向左或向右的行走.奔跑或跳跃功能. 游戏中的怪兽角色,会不断的左右循环行走

*C#(WPF)--矩阵拖动和矩阵动画(拖动展开,不足动画效果)

最近在研发新的项目,遇到了一个桌面模式下的难点--展开动画.之前动画这方面没做过,也许很多人开始做的时候也会遇到相关问题,因此我把几个重点及实际效果图总结展示出来: 我的开发环境是在VS2017下进行的,这个工具条主要功能是:一个工具条,可进行拖拉.可进行拖拉展开,可在拖动之后不足展开并反向继续展开剩下的部分: 一.[拖动]   拖动的核心代码是通过矩阵进行定位和拖动的,定位是以父容器为模板的.以下是核心代码(及效果图): 1 /// <summary> 2 /// 这里TitleBar代指最

android手机安全卫士、Kotlin漫画、支付宝动画、沉浸状态栏等源码

Android精选源码 轻量级底部导航栏 android手机卫士源码 android实现高仿今日头条源码 一个用Kotlin写的简单漫画App源码 android吐槽项目完整源码 实现可以滑动文字逐渐变色的TabLayout android实现将app隐藏加密功能的源码 android实现横向滚动的卡片堆叠布局 android仿支付宝的咻咻动画源码 android状态栏和沉浸式导航栏管理源码 Android优质博客 从BaseActivity与BaseFragment的封装谈起 这篇博客主要是从

如何解决IOS 动画中 Autolayout 与View Transforms的冲突

IOS 的动画放大与缩小,并非按照找它的中心点放大和缩小,而是左上角 .我分析了下原来是Autolayout 与View Transforms的冲突造成的. - (void) addSubviewWithZoomInAnimation:(UIView*)view duration:(float)secs option:(UIViewAnimationOptions)option { // first reduce the view to 1/100th of its original dimen

JS 实现无缝滚动动画原理(初学者入)

这段时间在教培训班的学生使用原生javascript实现无缝滚动的动画案例,做了这个原理演示的动画,分享给自学JS的朋友!博主希望对你们有帮助! 在讲解之前先看一下demo: demo:https://224137748.github.io/JS_warehouse/lunbo/domo.HTML源码:https://github.com/224137748/JS_warehouse/blob/master/lunbo/domo.HTML ps: 上面和下面的滚动进度是一致的,上面红色框是为了演

U3D帧动画的制作

1.打开动画编辑器(动画制作器!)windows标签下的Animation 2.点击新建一个动画,保存后进入动画编辑状态.注意新建后创建一个动画和控制器(animator Contrller),同时为当前物体添加一个animator组件. 3.选择添加property,可以选择让动画改变哪些参数. 本例中制作一个窗口打开和关闭的简单动画.通过缩放窗口大小来控制打开关闭的动画.所以添加一个Scale的参数. 4.先制作一个关闭的动画:第一帧的时候控制scale都为1,也就是正常大小.60帧的时候控