Unity-Survival Shooter笔记

官方视频教程地址Survival Shooter tutorial

角色控制

    void FixedUpdate ()
    {
        // Store the input axes.
        // Returns the value of the virtual axis identified by axisName with no smoothing filtering applied.
        float h = Input.GetAxisRaw ("Horizontal");
        float v = Input.GetAxisRaw ("Vertical");

        // Move the player around the scene.
        Move (h, v);

        // Turn the player to face the mouse cursor.
        Turning ();

        // Animate the player.
        Animating (h, v);
    }

    void Move (float h, float v)
    {
        // Set the movement vector based on the axis input.
        movement.Set (h, 0f, v);

        // Normalise the movement vector and make it proportional to the speed per second.
        movement = movement.normalized * speed * Time.deltaTime;

        // Move the player to it's current position plus the movement.
        playerRigidbody.MovePosition (transform.position + movement);
    }

Awake和Start,Awake在脚本实例被加载的时候被调用,而Start是在Awake之后Update之前调用的。感觉有点像cocos里的二段构造模式,start相当于init。

GetAxisRaw与GetAxis,不同之处在于得到的值是固定的不会有平滑过渡的变化。

    void Turning ()
    {
        // Create a ray from the mouse cursor on screen in the direction of the camera.
        Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition);

        // Create a RaycastHit variable to store information about what was hit by the ray.
        RaycastHit floorHit;

        // Perform the raycast and if it hits something on the floor layer...
        if (Physics.Raycast (camRay, out floorHit, camRayLength, floorMask)) {
            // Create a vector from the player to the point on the floor the raycast from the mouse hit.
            Vector3 playerToMouse = floorHit.point - transform.position;

            // Ensure the vector is entirely along the floor plane.
            playerToMouse.y = 0f;

            // Create a quaternion (rotation) based on looking down the vector from the player to the mouse.
            Quaternion newRotation = Quaternion.LookRotation (playerToMouse);

            // Set the player's rotation to this new rotation.
            playerRigidbody.MoveRotation (newRotation);
        }
    }

Camera.ScreenPointToRay,创建一条射线从摄像机到屏幕上某点,这里是鼠标点击位置。

Quaternion.LookRotation(forward : Vector3, upwards : Vector3 = Vector3.up),创建一个旋转,沿着forward(z轴)并且头部沿着upwards(y轴)的约束注视。也就是建立一个旋转,使z轴朝向view y轴朝向up。

相机跟踪

MainCamera 设置Orthographic模式(相机会均匀地渲染物体,没有透视感)。

    void Start ()
    {
        offset = transform.position - target.position;
    }

    void FixedUpdate ()
    {
        Vector3 targetCamPos = target.position + offset;
        transform.position = Vector3.Lerp (transform.position, targetCamPos, smoothing * Time.deltaTime);
    }

Vector3.Lerp,static function Lerp (from : Vector3, to : Vector3, t : float) : Vector3 根据t取值from,to之间。t值是从0到1范围,smoothing为5表示5秒内相机从原位置移动到目标坐标。

敌方角色控制

分别添加Capsule Collider和Sphere Collider,其中 Sphere Collider需要选择Is Trigger选项用来在攻击判断的碰撞检测。
添加Nav Mesh Agent,自动寻路组件。地图中的需要参与寻路的场景,确保它们的Navigation Static被勾选。参数设置完后需要选择Bake进行烘焙。

    void Awake ()
    {
        player = GameObject.FindGameObjectWithTag ("Player").transform;
        playerHealth = player.GetComponent <PlayerHealth> ();
        enemyHealth = GetComponent <EnemyHealth> ();
        nav = GetComponent <UnityEngine.AI.NavMeshAgent> ();
    }

    void Update ()
    {
        if (enemyHealth.currentHealth > 0 && playerHealth.currentHealth > 0) {
            // set TagetPositon
            nav.SetDestination (player.position);
        } else {
            nav.enabled = false;
        }
    }

射线碰撞检测

        // Set the shootRay so that it starts at the end of the gun and points forward from the barrel.
        shootRay.origin = transform.position;
        shootRay.direction = transform.forward;

        // Perform the raycast against gameobjects on the shootable layer and if it hits something...
        if (Physics.Raycast (shootRay, out shootHit, range, shootableMask)) {
            // Try and find an EnemyHealth script on the gameobject hit.
            EnemyHealth enemyHealth = shootHit.collider.GetComponent <EnemyHealth> ();

            // If the EnemyHealth component exist...
            if (enemyHealth != null) {
                // ... the enemy should take damage.
                enemyHealth.TakeDamage (damagePerShot, shootHit.point);
            }

            // Set the second position of the line renderer to the point the raycast hit.
            gunLine.SetPosition (1, shootHit.point);
        }
        // If the raycast didn't hit anything on the shootable layer...
        else {
            // ... set the second position of the line renderer to the fullest extent of the gun's range.
            gunLine.SetPosition (1, shootRay.origin + shootRay.direction * range);
        }

这里有个问题,前面在给enemy添加的两个碰撞体如果都勾选了isTrigger实际演示中射线碰撞就会检测不到。网上翻了下

Raycasts Hit Triggers If enabled = any Raycast that intersects with a Collider marked as a Trigger will return a hit. If disabled, these intersections will not return a hit.

Edit ->Project Setting->Physics->Queries Hit Triggers,勾选后可以解决问题,当然也可以其中一个碰撞体不勾选isTrigger。

角色生成

    InvokeRepeating ("Spawn", spawnTime, spawnTime);

    Invoke(methodName: string, time: float): void;
    methodName:方法名
    time:多少秒后执行

    InvokeRepeating(methodName: string, time: float, repeatRate:     float): void;
    methodName:方法名
    time:多少秒后执行
    repeatRate:重复执行间隔