角色控制(移动、旋转、跳跃等基本动作)(初学:4)

本文详细介绍在Unity3D中实现物体移动的多种方法,包括直接修改坐标、使用Translate函数和平滑移动,以及通过Rigidbody组件控制物体移动,提供代码示例并解析不同方法的特点。

在Unity3D中,有多种方式可以改变物体的坐标,实现移动的目的,其本质是每帧修改物体的position。以下代码均手打检验过。

利用transform组件

方法一:直接给游戏物体(也就是脚本所挂物体)的坐标进行 ± 步长即可

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

public class SphereMove : MonoBehaviour {

    // Use this for initialization
    private Vector3 Pos;
	void Start () {
        Pos = transform.localPosition;
        Debug.Log(Pos);
	}
	
	// Update is called once per frame
	void Update ()
    {
        if (Input.GetKeyDown(KeyCode.A)|Input.GetKeyDown(KeyCode.LeftArrow))//判断用户输入的是否是W或者键盘的左键键
        {
            Pos = new Vector3(Pos.x - 1, Pos.y, Pos.z);
            transform.localPosition = Pos;
            Debug.Log(transform.localPosition);
        }
        else if (Input.GetKeyDown(KeyCode.D) | Input.GetKeyDown(KeyCode.RightArrow))//判断用户输入的是否是D或者右键
        {
            Pos = new Vector3(Pos.x + 1, Pos.y, Pos.z);
            transform.localPosition = Pos;
            Debug.Log(transform.localPosition);
        }
        else if (Input.GetKeyDown(KeyCode.W) | Input.GetKeyDown(KeyCode.UpArrow))//判断用户输入的是否是W或者是上键
        {
            Pos = new Vector3(Pos.x, Pos.y, Pos.z - 1);
            transform.localPosition = Pos;
            Debug.Log(transform.localPosition);
        }
        else if (Input.GetKeyDown(KeyCode.S) | Input.GetKeyDown(KeyCode.DownArrow))//判断用户输入的是否是S或者是下键
        {
            Pos = new Vector3(Pos.x, Pos.y, Pos.z + 1);
            transform.localPosition = Pos;
            Debug.Log(transform.localPosition);
        }
        else if (Input.GetKeyDown(KeyCode.Space))
        {

            Pos = new Vector3(Pos.x, Pos.y + 1, Pos.z);
            transform.localPosition = Pos;
            Debug.Log(transform.localPosition);
            

        }
        else if (Input.GetKeyUp(KeyCode.Space))
        {
            Pos = new Vector3(Pos.x, Pos.y - 1, Pos.z);
            transform.localPosition = Pos;
            Debug.Log(transform.localPosition);
        }


    }
}

方法二:通过transform.Translate(v);函数来控制坐标
即:
Unity this.transform.Translate(Vector3.down * moveSpeed * Time.deltaTime)

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

public class SphereMove : MonoBehaviour {

    // Use this for initialization
    float speed = 1f;
	void Start () {
        
	}
	
	// Update is called once per frame
	void Update ()
    {
        float h = Input.GetAxis("Horizontal");
        float y = Input.GetAxis("Vertical");

        Vector3 v = new Vector3(h, 0, y);//构建新的移动变量可能是单方向也可能是两个方向
        v = v.normalized;//方向的标准化,也可以说是取单位
        v = v * speed * Time.deltaTime;//用Time.deltaTime来保证移动的每一帧速度都一样,不会因为帧数的大小而改变距离等
        transform.Translate(v);//共有两个参数,前面确定的是移动的方向和距离,后面的是坐标系的类型可能是世界坐标系也有可能是以自身为坐标系

    }
}

Time.delatime是本帧所用的时间,在前面的博客里面有解释过,假设这个值是个定值,那么也就是说Ts移动的单位距离是
MovespeedT,所以每秒的运动距离即为MovespeedT/T=Movespeed,而Movespeed是我们事先设置好的速度,也就是定值,这样就可以保证游戏物体每秒所移动的距离是个定值,不会随着帧数的改变而改变。

这两种方法共同之处就在于,必须要先获得键盘的相应,不同在于获取的方式不同,一个是通过Input.GetKey(),一个是通过Input.GetAxisRaw()获取。

注意:上面的两种方法都需要在Uodate方法中实现,切移动仅是二维坐标系上。
方法三:平滑的移动

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

public class ReboundMove : MonoBehaviour
{

    // Use this for initialization
    
    public float speed;
    public float xMin;
    public float xMax;
    
	void Start () {
        
	}

    // Update is called once per frame
    void Update()
    {

        float hor = Input.GetAxisRaw("Horizontal");//不会有一个速度渐变的过程而GetAxis(“”)有一个渐变的过程不是很适合我们
        //float ver = Input.GetAxis("")
        if (hor != 0)
        {
            Vector3 pos = transform.position;
            pos.x -= pos.x * speed * hor * Time.deltaTime;
            pos.x = Mathf.Clamp(pos.x, xMin, xMax);//限制x的范围
                                                   //或者写成判断的形式
            pos.x -= pos.x * speed * hor * Time.deltaTime;
            transform.position = pos;

        }
    }
}  

通过Rigibody组件

方法一:通过Rigibody类中的velocity方法控制
代码如下:

using System.Collections.Generic;
using UnityEngine;

public class SphereMove : MonoBehaviour {

    // Use this for initialization
    public Rigidbody Sp;
    private float speed = 10f;
	void Start () {
        Sp = GetComponent<Rigidbody>();
	}
	
	// Update is called once per frame
	void Update ()
    {
        float h = Input.GetAxis("Horizontal");
        float y = Input.GetAxis("Vertical");

        if (Input.GetKeyDown(KeyCode.W) | Input.GetKeyDown(KeyCode.S))
        {
            Sp.velocity = Vector3.forward * y * speed ;
        }
        if (Input.GetKeyDown(KeyCode.A) | Input.GetKeyDown(KeyCode.D))
        {
            Sp.velocity = Vector3.right * h * speed ;
        }
    }
}

这里需要注意的是:由于最开始的速度基数是零,所以游戏开始运行时,他是静止的,当你按下控制方向的键时,它会给游戏物体添加相应方向的速度,这个速度既有大小又有方向,也就是速度向量,并且这个速度向量是会叠加的,在添加刚体组件之后,记得考虑摩擦力,按下的瞬间,物体的速度的确是你设置的值,但是由于有摩擦力,会使速度变慢,当连续点击的时候他的速度叠加之后会变得很大。如果想要取消摩擦力,添加一个物理材质,在物理材质里面有取消摩擦力的选项。
Dynamic Friction 滑动摩擦
3: Static Firction 静态摩擦
4: Bounciness 表面弹性;
5: Friction Combine 摩擦力的混合方式
6: Bounciness Combine 弹力的混合方式;,Average就是每次弹完就取平均值,慢慢停下来

方法二:通过添加力来控制,即Rigidbody.AddForce()方法

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

public class SphereMove : MonoBehaviour {

    // Use this for initialization
    public Rigidbody Sp;//获取游戏物体的刚体组件
    
    public float Factor = 1f;//设定速度基数
    
	void Start ()
    {
        Sp = GetComponent<Rigidbody>();
        
	}
	
	// Update is called once per frame
	void Update ()
    {
        float horizontal = Input.GetAxis("Horizontal");//判断用户输入
        float vertical = Input.GetAxis("Vertical");
        if (Input.GetKeyDown(KeyCode.W) | Input.GetKeyDown(KeyCode.S))
        {
            Sp.AddForce(Vector3.forward * Factor* vertical , ForceMode.Impulse);
        }
        else if (Input.GetKeyDown(KeyCode.A) | Input.GetKeyDown(KeyCode.D))
        {
            Sp.AddForce(Vector3.right * horizontal * Factor, ForceMode.Impulse);
        }
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值