• Unity3D游戏开发从零单排(六)


    提要

    今天要实现的是一个简单人物控制器。

    包括用w,a,s,d来控制人物上下左右跑动,鼠标左击发出连招,都是基于老的lagacy的动画。尽管unity3d自带有charactorcontroller,可是并非非常好用,所以人物控制相关的所有自己来实现。先上效果图:



    场景搭建

    首先下载这个package,里面包括了人物的动作还有地面的模型。

    将人物和地面都拖进场景中。这里的模型默认的动画模式是lagacy,不用改动。模型有点偏小,改变模型的scale值为10.最好不要改源文件的scale的scale factor。可能会出现骨骼错位的问题。



    接下来给摄像机加入一个天空盒组件,加入一个unity自带的天空盒就好。

    对于人物还要加入几个component:


    加入Rigdbody来控制人物,选择IsKinematic,这样角色就不会被外力影响。加了CapsuleCollider让角色 不掉下去。

    HeroController用来控制角色的运动和打斗。以下会说。


    角色行走

    思路非常easy,通过wasd获得行走的方向,然后相应控制角色的位移就能够了,只是在变向的时候要注意角色的平滑转身。

    首先定义 一个 枚举变量,为角色可能的状态。

    	public enum ActionState
    	{
    		Attack_1,
    		Attack_2,
    		Attack_3_1,
    		Attack_3_2,
    		Attack_3_3,
    		Attack_4,
    		Fire,
    		Jump,
    		Run,
    		Idle
    	}
    	private ActionState actionState = ActionState.Idle;

    Animate函数来依据角色的状态播放相应的动画

    	void Animate()
    	{
    		float delayTime = -0.1f;
    
    		switch (actionState) {
    		case ActionState.Attack_3_1:
    			delayTime = -0.1f;
    			playerAnimation.CrossFade("Attack3-1", 0.15f);
    			currentAnimationClip = playerAnimation["Attack3-1"].clip;
    			break;
    		case ActionState.Attack_3_2:
    			delayTime = -0.1f;
    			playerAnimation.CrossFade("Attack3-2", 0.15f);
    			currentAnimationClip = playerAnimation["Attack3-2"].clip;
    			break;
    		case ActionState.Attack_3_3:
    			delayTime = -0.1f;
    			playerAnimation.CrossFade("Attack3-3", 0.15f);
    			currentAnimationClip = playerAnimation["Attack3-3"].clip;
    			break;
    		case ActionState.Attack_4:
    			delayTime = -0.1f;
    			playerAnimation.CrossFade("Attack4", 0.15f);
    			currentAnimationClip = playerAnimation["Attack4"].clip;
    			break;
    		case ActionState.Idle:
    			playerAnimation.CrossFade("Idle", 0.35f);
    			currentAnimationClip = playerAnimation["Idle"].clip;
    			break;
    		case ActionState.Jump:
    			playerAnimation.CrossFade("Jump", 0.15f);
    			currentAnimationClip = playerAnimation["Jump"].clip;
    			break;
    		case ActionState.Run:
    			playerAnimation.CrossFade("Run", 0.15f);
    			currentAnimationClip = playerAnimation["Run"].clip;
    			break;
    		case ActionState.Fire:
    			playerAnimation.CrossFade("Fire", 0.15f);
    			currentAnimationClip = playerAnimation["Fire"].clip;
    			break;
    		default: break;
    		}
    		//Switch to default if an animation is almost over
    		if (playerAnimation[currentAnimationClip.name].time > (playerAnimation[currentAnimationClip.name].length + delayTime)){
    			actionState = ActionState.Idle;
    			currentAnimationClip = playerAnimation["Idle"].clip;
    		}
    	}

    在update函数中加入相应的逻辑函数:

    	// Update is called once per frame
    	void Update () {
    
    		float h = Input.GetAxis("Horizontal");  
    		float v = Input.GetAxis("Vertical");  
    		MovementManagement (h, v);
    		Animate ();
    	}

    MovementManagement函数就是依据输入处理角色行走的

    	void MovementManagement(float horizontal, float vertical)
    	{
    		if(horizontal != 0f || vertical != 0f)
    		{
    			Rotating(horizontal, vertical);
    			actionState = ActionState.Run;
    			moveDirection = new Vector3(horizontal, 0.0f, vertical);
    			rigidbody.MovePosition(rigidbody.position + speed * moveDirection * Time.deltaTime);
    		}
    	}
    

    平滑转身函数(參考Unity官网的toturial)

    void Rotating(float horizontal, float vertival)
    	{
    		Vector3 targetDirection = new Vector3 (horizontal, 0f, vertival);
    		// Create a rotation based on this new vector assuming that up is the global y axis.
    		Quaternion targetRotation = Quaternion.LookRotation(targetDirection, Vector3.up);
    		
    		// Create a rotation that is an increment closer to the target rotation from the player's rotation.
    		Quaternion newRotation = Quaternion.Lerp(rigidbody.rotation, targetRotation, turnSmoothing * Time.deltaTime);
    		
    		// Change the players rotation to this new rotation.
    		rigidbody.MoveRotation(newRotation);
    	}

    因为这里是简单的平地,所以处理起来比較简单。当须要控制角色在复杂的地形上行走的时候,比方山川丘陵,就须要角色在Y方变化了。这个时候仅仅须要勾选角色的rigidbody component的 use gravity。然后限制rigidbody的x。z方向的移动了,x,z方向的移动要全然靠脚本来处理。


    角色连击

    首先来思考一下逻辑。

    角色初始值状态是Idle。此时按下攻击。发连招的第一招,假设玩家继续按的话就进入第二招,依次类推,假设中途停下的话,就还是回到Idle状态。这是最简单的单线连招的逻辑,没有考虑打断,多连等情况,代码实现例如以下:

    	void AttackLogic()
    	{
    		if (Input.GetButtonDown ("Fire1")) 
    		{
    			if(actionState != ActionState.Attack_3_1 && actionState != ActionState.Attack_3_2
    			   && actionState != ActionState.Attack_3_3&& actionState != ActionState.Attack_4)
    			{
    				Debug.Log ("Fire");
    				actionState = ActionState.Attack_3_1;
    			}
    			else if(actionState == ActionState.Attack_3_1 && playerAnimation[currentAnimationClip.name].time > 1.0f)
    			{
    				actionState = ActionState.Attack_3_2;
    			}
    			else if(actionState == ActionState.Attack_3_2 && playerAnimation[currentAnimationClip.name].time > 1.0f)
    			{
    				actionState = ActionState.Attack_3_3;
    			}
    			else if(actionState == ActionState.Attack_3_3 && playerAnimation[currentAnimationClip.name].time > 1.0f)
    			{
    				actionState = ActionState.Attack_4;
    			}
    			/*else if(actionState == ActionState.Attack_3 && playerAnimation[currentAnimationClip.name].time > 2.0f)
    			{
    				actionState = ActionState.Idle;
    			}*/
    				
    		}
    		else if(Input.GetButtonDown ("Jump"))
    		{
    			actionState = ActionState.Jump;
    		}
    		else if(Input.GetButtonDown ("Fire2"))
    		{
    			actionState = ActionState.Fire;
    			
    			//if (currentSkill==null)
    		}
    
    	}


    执行一下,就能够实现最開始的那个效果了。


    參考

    Unity3d toturial - Stealth

  • 相关阅读:
    [UE4]roll pitch yaw
    [UE4]用向量表示方向
    [UE4]关闭自动曝光
    Mysql数据库常用分库和分表方式
    mycat分库分表 mod-long
    windows安装mycat(转)
    Mycat读写分离、主从切换学习(转)
    Windows版Mycat结合mysql安装配置+水平切分(转载)
    数据库高性能读写分离集群操作说明
    spring MVC、mybatis配置读写分离,ReplicationDriver(转载)
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10018684.html
Copyright © 2020-2023  润新知