《Unity In Action》读书笔记(二)

子弹的轨迹是由2D坐标屏幕的camera位置射向3D坐标世界的某个点。

Unity中的协程不是异步的,yield之后退出,下一帧再接着执行。执行时机是在update()和lateUpdate()之间。适合用场合:如等待几秒后销毁,文件加载好后处理。

发射子弹并击中目标的代码:

    void Start() {
        _camera = GetComponent<Camera>();
        // 鼠标锁定且隐藏,按ESC解除锁定
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }
    // 在每一帧完成3D场景渲染后调用
    void OnGUI() {
        int size = 12;
        float posX = _camera.pixelWidth/2 - size/4;
        float posY = _camera.pixelHeight/2 - size/2;
        // 这里用基础GUI构造了一个TextLabel
        GUI.Label(new Rect(posX, posY, size, size), "*");
    }

    void Update() {
        if (Input.GetMouseButtonDown(0)) {
            // 从camera中心发出
            Vector3 point = new Vector3(_camera.pixelWidth/2, _camera.pixelHeight/2, 0);
            // 这个方法垂直屏幕发出射线
            Ray ray = _camera.ScreenPointToRay(point);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit)) {
                // 击中的对象
                GameObject hitObject = hit.transform.gameObject;
                ReactiveTarget target = hitObject.GetComponent<ReactiveTarget>();
                // 若找到相应脚本,则认为是敌人,否则是普通物体
                if (target != null) {
                    target.ReactToHit();
                } else {
                    StartCoroutine(SphereIndicator(hit.point));
                }
            }
        }
    }

    // 调用协程方法
    private IEnumerator SphereIndicator(Vector3 pos) {
        GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        sphere.transform.position = pos;
        // 暂停1秒再销毁
        yield return new WaitForSeconds(1);

        Destroy(sphere);
    }

tweens可以让敌人被击中后倾斜的动作更加顺滑。

敌人AI代码:

    void Start() {
        _alive = true;
    }

    void Update() {
        if (_alive) {
            // 1. 向前移动(rotate()和translate()都默认使用本地坐标系)
            transform.Translate(0, 0, speed * Time.deltaTime);

            Ray ray = new Ray(transform.position, transform.forward);
            RaycastHit hit;
            if (Physics.SphereCast(ray, 0.75f, out hit)) {
                GameObject hitObject = hit.transform.gameObject;
                // 2. 若发射线击中物体了
                if (hitObject.GetComponent<PlayerCharacter>()) {
                    // 若没有火球则产生火球
                    if (_fireball == null) {
                        _fireball = Instantiate(fireballPrefab) as GameObject;
                        _fireball.transform.position = transform.TransformPoint(Vector3.forward * 1.5f);
                        _fireball.transform.rotation = transform.rotation;
                    }
                }
                // 3. 若在一定范围内
                else if (hit.distance < obstacleRange) {
                    // 4. 则旋转随机角度
                    float angle = Random.Range(-110, 110);
                    transform.Rotate(0, angle, 0);
                }
            }
        }
    }

prefab是可被不同场景重复使用的GameObject,它可以看做是一种asset,在场景中需要使用时动态加载,这时产生的一个copy叫做instance。关键词:动态加载,重复使用。

敌人死亡后重生的做法是:创建一个空GameObject,下面挂载一个脚本SceneController,每帧判断下当前场景中是否有enemy prefab的instance,没有则创建。

火球运动的代码:

    void Update() {
        transform.Translate(0, 0, speed * Time.deltaTime);
    }

    // 碰撞时触发(需要设置rigidBody)
    void OnTriggerEnter(Collider other) {
        PlayerCharacter player = other.GetComponent<PlayerCharacter>();
        if (player != null) {
            // 执行扣血代码
            player.Hurt(damage);
        }
        Destroy(this.gameObject);
    }

敌人和玩家子弹的处理不一样,一个是用prefab,可以看到移动过程;另一个是raycast,瞬间击中。

art asset的类型分类:material, texture, model, animation, particle system。

Unity支持的2D图形文件类型:PNG,JPG,GIF,BMP,TGA,TIFF,PICT,PSD。其中PNG是无损压缩,JPG和GIF是有损压缩。Unity中推荐使用的格式是:PNG,TGA和PSD。

将texture应用到model的方法:可以直接拖拽到model上,这时material会自动生成;也可以先创建material,再将texture和material关联。

Unity支持的3D模型格式有:FBX,Collada,OBJ,3DS,DXF,Maya,3ds Max,Blender。推荐的是FBX和Collada,它们同时支持mesh和animation。

粒子系统用于表现大量物体的运动(如火焰、烟雾、水)。

猜你喜欢

转载自blog.csdn.net/needmorecode/article/details/80045494
今日推荐