unity3d 人物的移动跳跃

2017-04-16 15:09:41 mian199614 阅读数 24569
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

首先给对象添加刚体和碰撞体。

在FixedUpdate中写入如下代码,不能是Update,因为是物理属性,必须要FixedUpdate

GetComponent<Rigidbody>().velocity += new Vector3(0, 5, 0); //添加加速度
GetComponent<Rigidbody>().AddForce(Vector3.up * mJumpSpeed); //给刚体一个向上的力,力的大小为Vector3.up*mJumpSpeed

完整代码如下



        transform.rotation = Quaternion.LookRotation(Vector3.forward, Vector3.up);
         if (Input.GetButtonDown("Jump"))
        {
            if (ground == true)
            {   


                //transform.Translate(new Vector3(Input.GetAxis("Horizontal")*distance, 2, Input.GetAxis("Vertical")*distance));
                GetComponent<Rigidbody>().velocity += new Vector3(0, 5, 0);
                GetComponent<Rigidbody>().AddForce(Vector3.up * mJumpSpeed);
                ground = false;
                Debug.Log("I am Pressing Jump");
            }
        }

ground用来判断你是在空中还是地面,如果是在空中,当然不能再让你跳。

另外如果要取消反冲力,在start方法里加GetComponent<Rigidbody>().freezeRotation = true;

2016-05-10 09:35:13 LucienDuan 阅读数 18051
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

在Unity3D中控制人物移动的方法很多,可以使用transform.Translate方法,但为了不穿越其他物体,需要使用刚体rigidbody。还可以使用角色控制器,角色控制器是自带刚体Rigidbody和碰撞器Collider的,移动可以使用CharacterController组件。

在使用CharacterController组件实现跳跃时,需要检测人物是否在地面上,CharacterController提供了属性isGrounded以供检测,但是在使用中发现isGrounded总是返回false,没有找到原因,因此替代使用射线检测方法来判断是否着地,射线检测其实就是用从人物身体发射一条向下的射线判断射线在给定距离内是否碰撞物体即可以判断是否着地。代码如下:

	public float speed = 1;

	public float jumpSpeed = 10;

	public float gravity = 20;

	public float margin = 0.1f;

	private Vector3 moveDirection = Vector3.zero;

	// 通过射线检测主角是否落在地面或者物体上
	bool IsGrounded() {
		return Physics.Raycast(transform.position, -Vector3.up,  margin);
	}

	// Update is called once per frame
	void Update () {
		// 控制移动
		float h = Input.GetAxis ("Horizontal");
		float v = Input.GetAxis ("Vertical");

		if (IsGrounded()) {
			moveDirection = new Vector3 (h, 0, v);
			moveDirection = transform.TransformDirection (moveDirection);
			moveDirection *= speed;
			// 空格键控制跳跃
			if (Input.GetButton ("Jump")) {
				moveDirection.y = jumpSpeed;
			}
		}
		moveDirection.y -= gravity * Time.deltaTime;
		controller.Move (moveDirection * Time.deltaTime);
	}






2017-10-17 09:03:42 q764424567 阅读数 1841
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

Unity3D Player角色移动控制脚本

在Unity3D中,有多种方式可以改变物体的坐标,实现移动的目的,其本质是每帧修改物体的position。我针对角色移动做了一下盘点,并给出了一些常用API的脚本,每个脚本均已测试可用

1.通过Transform组件移动物体

Transform组件用于描述物体在空间中的状态,它包括位置(position),旋转(rotation)和缩放(scale)。 其实所有的移动都会导致position的改变,这里所说的通过Transform组件来移动物体,指的是直接操作Transform来控制物体的位置(position)。
Transform.Translate
该方法可以将物体从当前位置,移动到指定位置,并且可以选择参照的坐标系。 当需要进行坐标系转换时,可以考虑使用该方法以省去转换坐标系的步骤。

	public float m_speed = 5f;
	//Translate移动控制函数
    void MoveControlByTranslate()
    {
        if (Input.GetKey(KeyCode.W)|Input.GetKey(KeyCode.UpArrow)) //前
        {
            this.transform.Translate(Vector3.forward*m_speed*Time.deltaTime);
        }
        if (Input.GetKey(KeyCode.S) | Input.GetKey(KeyCode.DownArrow)) //后
        {
            this.transform.Translate(Vector3.forward *- m_speed * Time.deltaTime);
        }
        if (Input.GetKey(KeyCode.A) | Input.GetKey(KeyCode.LeftArrow)) //左
        {
            this.transform.Translate(Vector3.right *-m_speed * Time.deltaTime);
        }
        if (Input.GetKey(KeyCode.D) | Input.GetKey(KeyCode.RightArrow)) //右
        {
            this.transform.Translate(Vector3.right * m_speed * Time.deltaTime);
        }
    }

或者

	 //Translate移动控制函数
    void MoveControlByTranslateGetAxis()
    {
        float horizontal = Input.GetAxis("Horizontal"); //A D 左右
        float vertical = Input.GetAxis("Vertical"); //W S 上 下

        transform.Translate(Vector3.forward * vertical * m_speed * Time.deltaTime);//W S 上 下
        transform.Translate(Vector3.right * horizontal * m_speed * Time.deltaTime);//A D 左右
    }

Vector3.Lerp, Vector3.Slerp, Vector3.MoveTowards
Vector3既可以表示三维空间中的一个点,也可以表示一个向量。这三个方法均为插值方法,Lerp为线性插值,Slerp为球形插值,MoveTowards在Lerp的基础上增加了限制最大速度功能。 当需要从指定A点移动到B点时,可以考虑时候这些方法。
Vector3.SmoothDamp
该方法是可以平滑的从A逐渐移动到B点,并且可以控制速度,最常见的用法是相机跟随目标。
Transform.position
有时重新赋值position能更快实现我们的目标。

2.通过Rigidbody组件移动物体

Rigidbody组件用于模拟物体的物理状态,比如物体受重力影响,物体被碰撞后的击飞等等。
注意:关于Rigidbody的调用均应放在FixedUpdate方法中,该方法会在每一次执行物理模拟前被调用。
Rigidbody.velocity
设置刚体速度可以让物体运动并且忽略静摩擦力,这会让物体快速从静止状态进入运动状态。

 	//Velocity移动控制函数
    void MoveControlByVelocity()
    {
        float horizontal = Input.GetAxis("Horizontal"); //A D 左右
        float vertical = Input.GetAxis("Vertical"); //W S 上 下
        //这个必须分开判断 因为一个物体的速度只有一个
        if (Input.GetKey(KeyCode.W) | Input.GetKey(KeyCode.S))
        {
            m_rigidbody.velocity = Vector3.forward * vertical * m_speed;
        }
        if (Input.GetKey(KeyCode.A)|Input.GetKey(KeyCode.D))
        {
            m_rigidbody.velocity = Vector3.right * horizontal * m_speed;
        }   
    }

Rigidbody.AddForce
给刚体添加一个方向的力,这种方式适合模拟物体在外力的作用下的运动状态。

	//AddForce移动控制函数
    void MoveControlByAddForce()
    {
        float horizontal = Input.GetAxis("Horizontal"); //A D 左右
        float vertical = Input.GetAxis("Vertical"); //W S 上 下

        m_rigidbody.AddForce(Vector3.forward * vertical * m_speed);
        m_rigidbody.AddForce(Vector3.right * horizontal * m_speed);  

    }

Rigidbody.MovePosition
刚体受到物理约束的情况下,移动到指定点。

3.通过CharacterController组件移动物体

CharacterController用于控制第一人称或第三人称角色的运动,使用这种方式可以模拟人的一些行为,比如限制角色爬坡的最大斜度,步伐的高度等。
CharacterController.SimpleMove
用于模拟简单运动,并且自动应用重力,返回值表示角色当前是否着地。

//SimpleMove移动控制函数 角色控制器
    void MoveControlBySimpleMove()
    {
        float horizontal = Input.GetAxis("Horizontal"); //A D 左右
        float vertical = Input.GetAxis("Vertical"); //W S 上 下

        m_character.SimpleMove(transform.forward * vertical * m_speed); 
    }

CharacterController.Move
模拟更复杂的运动,重力需要通过代码实现,返回值表示角色与周围的碰撞信息。

	//Move移动控制函数 角色控制器
    void MoveControlByMove()
    {
        float horizontal = Input.GetAxis("Horizontal"); //A D 左右
        float vertical = Input.GetAxis("Vertical"); //W S 上 下
        float moveY = 0; m_gravity=10f;
        moveY-= m_gravity * Time.deltaTime;//重力

        m_character.Move(new Vector3(horizontal, moveY, vertical) * m_speed * Time.deltaTime);
    }
2018-01-01 13:49:13 A13155283231 阅读数 7029
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

要添加动画状态机

public class PlayerController : MonoBehaviour {

    Vector3 movement;
    Rigidbody playerRigidbody;
    Animator animator;

    // player移动速度
    public float speed = 6f;

    private float x;
    private float y;
    private float xSpeed = 2;
    private float ySpeed = 2;
    private Quaternion direct; // player direct

    // 判断是否落地
    private bool grounded = true;

    void Awake()
    {
        playerRigidbody = GetComponent<Rigidbody>();
        animator = GetComponent<Animator>();
    }

    void Update() {
        // keyboard move
        float h = Input.GetAxisRaw("Horizontal"); // A D
        float v = Input.GetAxisRaw("Vertical");   // W S

        // animating
        bool walking = h != 0f || v != 0f;
        animator.SetBool("Forward", walking);

        transform.Translate(Vector3.forward * v * speed * Time.deltaTime); // W S 上 下
        transform.Translate(Vector3.right * h * speed * Time.deltaTime); // A D 左右

        // Jump
        if (Input.GetButtonDown("Jump")) {
            if (grounded == true)
            {
                animator.SetBool("Jump", true);
                playerRigidbody.velocity += new Vector3(0, 5, 0); //添加加速度
                playerRigidbody.AddForce(Vector3.up * 50); //给刚体一个向上的力,力的大小为Vector3.up*mJumpSpeed
                grounded = false;
            }
        }


        // mouse move
        x += Input.GetAxis("Mouse X") * xSpeed;
        y -= Input.GetAxis("Mouse Y") * ySpeed;

        direct = Quaternion.Euler(y, x, 0);
        transform.rotation = direct;
    }

    // 落地检测
    void OnCollisionEnter(Collision collision) {
        animator.SetBool("Jump", false);
        grounded = true;
    }
}
2018-07-27 18:18:52 u013628121 阅读数 3492
  • Unity 值得看的500+ 技术内容列表

    Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎。

using UnityEngine;
using UnityEngine.AI;

public class SpaceJump : MonoBehaviour
{
    public float distance = 5f;
    public float hight = 8f;
    public float useTime = 1.5f;
    public KeyCode JumpKeyCode = KeyCode.Space;
    public bool isJumping = false;//是否在跳跃中
    public bool isContinueJump = true;//是否允许连跳
    public int jumpCountMax = 5;//最高允许连跳几次
    public int currJumpCount = 0;//当前连跳次数
    Vector3 addForce;
    private Rigidbody rigidbody;
    private NavMeshAgent agent;

    void Awake()
    {
        rigidbody = GetComponent<Rigidbody>();
        agent = GetComponent<NavMeshAgent>();
    }

    void FixedUpdate()
    {
        if (Input.GetKeyDown(JumpKeyCode)) Jump();
        if (isJumping && rigidbody && rigidbody.velocity.y == 0) JumpOver();// 落地
    }

    /// <summary>
    /// 跳跃结束
    /// </summary>
    public void JumpOver()
    {
        isJumping = false;
        if (rigidbody)
        {
            currJumpCount = 0;
            addForce = Vector3.zero;
            rigidbody.velocity = Vector3.zero;
        }
    }

    void iTweenJump()
    {
        Vector3 p2;//角色落点
        Vector3 p1;//最高点
        Vector3 dir = GetToMouseDir();//方向是跳向鼠标,transform.forward是跳向前方
        p1 = transform.position + dir * (distance / 2) + transform.up * hight;//第二个点:起始位置前方几米处上方几米的坐标.
        p2 = transform.position + dir * distance;
        //找到碰撞器 落脚点
        RaycastHit raycastHit; //碰撞体信息
        if (Physics.Raycast(p2, Vector3.down, out raycastHit, 81f))
        {
            p2 = raycastHit.point;
        }
        Vector3[] paths = new Vector3[3];
        paths[0] = transform.position;
        paths[1] = p1;
        paths[2] = p2;
        iTween.MoveTo(gameObject, iTween.Hash("path", paths, "movetopath", true, "time", useTime, "oncomplete", "JumpOver"));//movetopath=false按点移动,=true按照点构成的曲线路径移动
    }

    /// <summary>
    ///角色坐标 到 鼠标位置的方向
    /// </summary>
    Vector3 GetToMouseDir()
    {
        Vector3 dir = Vector3.forward;
        //从射相机的近裁剪面 开始并穿过 屏幕中鼠标像素坐标 的射线,从摄像机通过一个屏幕点的射线
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit = new RaycastHit();
        if (Physics.Raycast(ray, out hit))
        {
            Vector3 hitPos = hit.point;
            Vector3 playerPos = transform.position;
            //向量减法 和y无关,所以同步一下高度
            playerPos.y = hitPos.y;
            //向量减法,得到一个向量,包含方向和距离
            dir = (hitPos - playerPos);
            //归一化 去除距离 ,只要方向,如果不去除距离 ,那么角色闪到鼠标点击的位置
            dir = dir.normalized;
        }
        return dir;
    }

    void RigidbodyJump()
    {
        if (isJumping)
        {
            if (isContinueJump)
            {
                if (currJumpCount >= jumpCountMax)
                {
                    return;
                }
            }
            else
            {
                return;
            }
        }
        currJumpCount += 1;
        //打开刚体移动
        rigidbody.constraints = RigidbodyConstraints.None;
        rigidbody.constraints = RigidbodyConstraints.FreezeRotation;
        //角色当前刚体速度
        float xSpeed = 0;
        float zSpeed = 0;
        if (agent == null || agent.enabled == false)
        {
            xSpeed = rigidbody.velocity.x;
            zSpeed = rigidbody.velocity.z;
        }
        else
        {
            xSpeed = agent.velocity.x;
            zSpeed = agent.velocity.z;
            agent.enabled = false;
        }
        Vector3 add;
        if (xSpeed == 0 && zSpeed == 0)
        {//站立状态:向上眺
            add = transform.up * hight;
            rigidbody.velocity += add;
        }
        else
        {//移动状态:向鼠标方向跳
            Vector3 dir = GetToMouseDir();
            add = dir * distance + transform.up * hight;
            if (addForce == Vector3.zero)
            {//判断是第一次跳跃,就跳固定值高度
                rigidbody.velocity = add;
            }
            else
            {
                rigidbody.velocity += add;
            }
        }
        addForce += add;
        //Debug.LogError("Rigidbody" + GetComponent<Rigidbody>().velocity+"zSpeed:" + zSpeed+ "xSpeed:"+ xSpeed+"dir:" + dir+"add"  + add+"rigidbody.velocity = " +rigidbody.velocity + "force" + addForce);
        rigidbody.AddForce(addForce);
        // 设置 角色状态  动画 等为跳跃
    }

    public void Jump()
    {
        if (rigidbody)
        {
            RigidbodyJump();
        }
        else
        {
            iTweenJump();
        }
        isJumping = true;
    }

}