unity2D笔记-控制人物相关

(一)左右移动

控制人物左右移动,同时加入左右移动人物翻转控制。
有两种方法:
1.更新 x的速度,通过速度正负判断翻转。(注释的代码)
2.获取位置帧,通过位置帧和初始帧的大小判断是否翻转。(注释的代码)
3.根据轴判断,是否翻转和左右移动。
Tips:
Input.GetAxisRaw: 获取原始轴
按下键的時候取得的值只有0,1,-1 这3个值

Input.GetAxis: 获取轴
按下键的時候取得的值会从0到1慢慢增加
比如: 0 - 0.123 - 0.245 - 0.672 - 0.89 - 1.0

乘以Time.deltaTime来获得平滑运动效果

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player: MonoBehaviour
{
    Rigidbody2D rigidbody2d;
    // Start is called before the first frame update
    SpriteRenderer spriteRenderer;
    public float speedX; //X方向的速度
    void Start()
    {
        //获取刚体属性
        rigidbody2d = transform.GetComponent<Rigidbody2D>();
        //
        spriteRenderer =transform.GetComponent<SpriteRenderer>();
       
    }

    // Update is called once per frame
    void Update()
    {
    //(方法一)
        // if(Input.GetKey(KeyCode.A)){
        //     SetSpeedX(-speedX);
        // }
        //   if(Input.GetKey(KeyCode.D)){
        //    SetSpeedX(speedX);
        //  }
        //  if(!Input.GetKey(KeyCode.A)&&!Input.GetKey(KeyCode.D)){
        //      SetSpeedX(0);
        //  }
   //(方法二)
        //由于是只控制左右,因此Y值拿刚体默认的速度值即可
    /*    Vector2 movement = new Vector2(Input.GetAxisRaw("Horizontal"), rigidbody2d.velocity.y);
        Vector2 startPos = rigidbody2d.position;
        Vector2 targetPos = rigidbody2d.position + movement * Time.deltaTime * speedX;
        if(targetPos.x < startPos.x)
        {
            spriteRenderer.flipX = true;
        }
        else
        {
            spriteRenderer.flipX = false;
        }
        rigidbody2d.MovePosition(targetPos);
    }*/
	//(方法三)
	float horizontalmove = Input.GetAxis("Horizontal");
	if(horizontalmove!=0){
	rigidbody2d.velocity = new Vector2(speedX*horizontalmove*Time.deltaTime,rigidbody2d.velocity.y);
	}
	//控制人物翻转 通过获取原始轴进行反转 只控制x轴 当x的scale是-1时 会产生翻转
	float direction = Input.GetAxisRaw("Horizontal");
	if(direction!=0) transform.localScale = Vector3(direction,1,1);
	
 }
 /*   #region 控制速度方法
    public void SetSpeedX(float x){
    if(x<0)
    {
        //控制翻转
        spriteRenderer.flipX=true;
    }else if(x>0){
        spriteRenderer.flipX=false;
    }
    rigidbody2d.velocity = new Vector2(x,rigidbody2d.velocity.y);
}
public void SetSpeedY(float y){
     rigidbody2d.velocity = new Vector2(rigidbody2d.velocity.x,y);
}
#endregion*/
}
 

(二)奔跑

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player: MonoBehaviour
{
    Rigidbody2D rigidbody2d;
    // Start is called before the first frame update
    SpriteRenderer spriteRenderer;
    public float speedX; //X方向的速度
    Animator animator; //动画状态机 默认状态 和奔跑状态
    void Start()
    {
        //获取刚体属性
        rigidbody2d = transform.GetComponent<Rigidbody2D>();
        //
        spriteRenderer =transform.GetComponent<SpriteRenderer>();
        animator = transform.GetComponent<Animator>();
       
    }

    // Update is called once per frame
    void Update()
    {
        // if(Input.GetKey(KeyCode.A)){
        //     SetSpeedX(-speedX);
        // }
        //   if(Input.GetKey(KeyCode.D)){
        //    SetSpeedX(speedX);
        //  }
        //  if(!Input.GetKey(KeyCode.A)&&!Input.GetKey(KeyCode.D)){
        //      SetSpeedX(0);
        //  }
        Vector2 movement = new Vector2(Input.GetAxisRaw("Horizontal"), rigidbody2d.velocity.y);
        Vector2 startPos = rigidbody2d.position;
        Vector2 targetPos = rigidbody2d.position + movement * Time.deltaTime * speedX;
        if(targetPos.x < startPos.x)
        {
            spriteRenderer.flipX = true;
            animator.SetBool("is_run", true);
        }
        else if(targetPos.x == startPos.x)//静止 因此不改变为奔跑状态
        {
            animator.SetBool("is_run", false); ;
        }
        else {
            spriteRenderer.flipX = false;
            animator.SetBool("is_run", true);
        }
        rigidbody2d.MovePosition(targetPos);
    }
}
 

状态机图

(三)跳跃

1.之前的繁琐版本:

    float timerY;//上跳计时器
    public bool isGround; //是否在地面
    public bool jump;//跳跃状态
        if (Input.GetKeyDown(KeyCode.Space)&&isGround) //在地面时 且按下空格才可以跳跃
        {
            timerY = 0;
            jump = true;
        }
        if (Input.GetKey(KeyCode.Space)&&jump)
        {
            timerY += Time.deltaTime;
            if (timerY < 0.15f)
            {
                SetSpeedY(speedY);
                jump = true;
            }
            else
            {
                jump = false;
            }
        }
        if (Input.GetKeyUp(KeyCode.Space)) 
        {
            jump = false;
        }
        if (jump) { SetSpeedY(speedY); }
  
        checkGround();
        animator.SetBool("isJump", !isGround);
    	public void  checkGround() {
        RaycastHit2D raycastHit2D = Physics2D.Raycast(transform.position + Vector3.up, Vector3.down, 3.0f, 1 << 8);
        //发出射线 参数:当前位置坐标, 发射射线方位, 射线距离 , 检测的层级(地面层级为8)
        Debug.DrawLine(transform.position+Vector3.up, transform.position + Vector3.down * 0.2f,Color.red);
        isGround = raycastHit2D;

       //if (raycastHit2D)
       // {
       //     Debug.Log("检测到游戏物体:" + raycastHit2D.collider.gameObject.name);
       // }


    }
if(Input.GetButtonDown("Jump"))//默认Jump时空格
rigidbody2d.velocity =new Vector2(rigidbody.velocity.x,jumpforce*Time.deltaTime);

在这里插入图片描述
2.改进后的版本
状态机状态设置: run->up: isUp:true
idel->up:isUp:true
up->down:isDown:true
down->idel:isStand:true

在这里插入图片描述

  CapsuleCollider2D capsulecollider;
 public LayerMask ground;//选取TILEMAP图层的图层号
 capsulecollider = GetComponent<CapsuleCollider2D>(); // 获取胶囊型碰撞体
    void Jump()
    {
        if (capsulecollider.IsTouchingLayers(ground))
        {
            animator.SetBool("isDown", false);
            animator.SetBool("isStand", true);
            animator.SetBool("isUp", false);
           // animator.SetBool("isRun", false);
            if (Input.GetKeyDown(KeyCode.Space))
            {
                rigidbody2d.velocity = new Vector2(rigidbody2d.velocity.x, jumpforce);
                animator.SetBool("isUp", true);
                animator.SetBool("isStand", false);
                animator.SetBool("isDown", false);
                //animator.SetBool("isRun", false);
            }
        }
        else
        {
            if (rigidbody2d.velocity.y < 0)
            {
                animator.SetBool("isDown", true);
                animator.SetBool("isUp", false);
                animator.SetBool("isStand", false);
                //animator.SetBool("isRun", false);
            }
        }
    }

(四)相机跟随

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FollowTarget : MonoBehaviour
{
    // Start is called before the first frame update
    public Transform target;
    public Vector2 rangeMin;
    public Vector2 rangeMax;
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        Follow();
    }
    public void Follow()
    {
        if(target == null)
        {
            Debug.LogWarning("跟随目标为空");
        }
        Vector3 targetPos = new Vector3(target.position.x, target.position.y, transform.position.z);
        transform.position =LimitPos(targetPos);
    }
    public Vector3 LimitPos(Vector3 targetPos)
    {
        return new Vector3(Mathf.Clamp(targetPos.position.x, rangeMin.x, rangeMax.x),
        Mathf.Clamp(targetPos.position.y, rangeMin.y, rangeMax.y),transform.position.z);
    }
}

(四)增加下蹲和代码优化

通过三种方法来更新物体运动:1.状态 2.速度 3.动画

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum PlayerStatus{
    Stand  =0,
    Up = 1,
    Down = 2,
    Crouch = 3,
    Run = 4,
}
public class Player: MonoBehaviour
{
    Rigidbody2D rigidbody2d;
    // Start is called before the first frame update
    SpriteRenderer spriteRenderer;
    public float speedX; //X方向的速度
    public float jumpforce;
    Animator animator; //动画状态机 默认状态 和奔跑状态
    CapsuleCollider2D capsulecollider;
    public LayerMask ground;
    public PlayerStatus curState = PlayerStatus.Stand;
    Transform followTarget; //相机跟随目标
    public Vector3 followTargetOffset; //跟随偏移量
    void Start()
    {
        //获取刚体属性
        rigidbody2d = transform.GetComponent<Rigidbody2D>();
        //
        spriteRenderer =transform.GetComponent<SpriteRenderer>();
        animator = transform.GetComponent<Animator>();
        capsulecollider = GetComponent<CapsuleCollider2D>(); // 获取胶囊型碰撞体
        followTarget = transform.Find("followTarget");
        followTarget.position = transform.position + followTargetOffset;
    }

    // Update is called once per frame
    void Update()
    {   
        UpdateState();
        UpdateSpeed(); 
        UpdateAnimator();
        UpdateFollowTargetPos();
    }
    public void SetSpeedY(float y)
    {
        rigidbody2d.velocity = new Vector2(rigidbody2d.velocity.x, y);
        rigidbody2d.constraints = RigidbodyConstraints2D.FreezeRotation;
        if (curState == PlayerStatus.Crouch)
        {
            rigidbody2d.constraints = RigidbodyConstraints2D.FreezePositionY;
        }
    }

    public void SetSpeedX(float x)
    {
        rigidbody2d.velocity = new Vector2(x, rigidbody2d.velocity.y);
        //控制人物翻转 通过获取原始轴进行反转 只控制x轴 当x的scale是-1时 会产生翻转
        float direction = Input.GetAxisRaw("Horizontal");
        if (direction != 0) transform.localScale = new Vector3(direction, 1, 1);
        rigidbody2d.constraints = RigidbodyConstraints2D.FreezeRotation;
        //下蹲时冻结X轴移动
        if (curState == PlayerStatus.Crouch)
        {
            rigidbody2d.constraints = RigidbodyConstraints2D.FreezePositionX;
        }

    }
    public void UpdateFollowTargetPos()
    {
        float direction = Input.GetAxisRaw("Horizontal");
        if (direction != 0)
        {
            followTarget.position = Vector3.MoveTowards(followTarget.position, transform.position - followTargetOffset,0.1f);
        }
        else
        {
            followTarget.position = Vector3.MoveTowards(followTarget.position, transform.position + followTargetOffset, 0.1f);
        }
    }
    public void UpdateSpeed()
    {
        if (PlayerInput.instance.Jump.Down && capsulecollider.IsTouchingLayers(ground))
        {
            SetSpeedY(jumpforce);
        }
        SetSpeedX(PlayerInput.instance.Horizontal.value * speedX);
    }
    public void UpdateState()
    {
        curState = PlayerStatus.Stand;
        if (rigidbody2d.velocity.x != 0)
        {
            curState = PlayerStatus.Run;
        }
        if (!capsulecollider.IsTouchingLayers(ground))
        {
            if (rigidbody2d.velocity.y < 0)
            {
                curState = PlayerStatus.Down;

            }
            else
            {
                curState = PlayerStatus.Up;
            }
        }
        if(PlayerInput.instance.Veritical.value == -1&& capsulecollider.IsTouchingLayers(ground))
        {
            curState = PlayerStatus.Crouch;
        }
       
    }
    public void UpdateAnimator()
    {
        animator.SetBool("isUp", false);
        animator.SetBool("isStand", false);
        animator.SetBool("isDown", false);
        animator.SetBool("isCrouch", false);
        animator.SetBool("isRun", false);
        if (curState == PlayerStatus.Run)
        {
            animator.SetBool("isRun", true);
        }
        if (curState == PlayerStatus.Up)
        {
            animator.SetBool("isUp", true);
            //animator.SetBool("isStand", false);
           // animator.SetBool("isDown", false);
        }
        if (curState == PlayerStatus.Down)
        {
            animator.SetBool("isDown", true);
            //animator.SetBool("isUp", false);
            //animator.SetBool("isStand", false);
        }
        if (curState == PlayerStatus.Stand)
        {
            //animator.SetBool("isDown", false);
           // animator.SetBool("isUp", false);
            animator.SetBool("isStand", true);
        }
        if (curState == PlayerStatus.Crouch)
        {
            animator.SetBool("isCrouch", true);
        }
    }
}
 
 

作更新:状态最好使用Trigger,Trigger的本质其实和bool一样,但是Trigger会在实行完毕后,将状态设置为取反状态,如果默认是False,那么在执行了true条件后,系统会将Trigger重新置为false。
这里就不需要对每次状态进行置位false了。

    public void UpdateAnimator()
    {
        switch (curState)
        {
            case PlayerStatus.Run:
                animator.SetTrigger("isRun");
                break;
            case PlayerStatus.Jump:
                animator.SetTrigger("isJump");
                break;
            case PlayerStatus.Stand:
                animator.SetTrigger("isStand");
                break;
            case PlayerStatus.Crouch:
                animator.SetTrigger("isCrouch");
                break;

        }
    }
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值