光源,摄像机,简单的工厂

本文总结了Unity3D中摄像机和光源的使用,包括摄像机的角度调整、Field of View设置、Camera的静态属性及其在场景中的应用。同时,探讨了面向对象设计中的超类与接口的区别,并介绍了如何利用简单工厂模式在游戏开发中添加新的动作行为。
摘要由CSDN通过智能技术生成

摄像机用法总结


如何应用左手法则决定方向,应用 Field of view 设置场景大小

首先说明左手定则的应用是在unity中物体旋转方向的确定,据一个例子:

首先我放置一个camera,一个物体,让camera能照射到物体:

这里写图片描述

此时camera的坐标和角度是如下的:

这里写图片描述

目前的我的观察角度是在 “从y轴看下去”更形象一点就是 “Y轴箭头扎眼睛的方向”,我改变camera的y轴rotate的值如下:

这里写图片描述

摄像机角度改变如下:

这里写图片描述

如图所示,摄像机是旋转方向为 顺时针,如果将y轴替换为大拇指,则旋的方向为4个手指的方向,也就是左手定则

应用Field of views改变场景大小,例子如下:

其实Field of views 就是视角,因为Unity中,也是把对象投影在一个范围内的,所以也会有视角这个设定,比如说人的视角差不多是120度,而《火影忍者》里宁次的视角差不多是360度,所以他可以看到背后的敌人。鱼的双眼视角差不多也是360度,摄像机只能模仿一个眼睛的效果,如下:

这里写图片描述


Camera 继承的类

从源码看 Camera 是继承于 Behaviour 类的,而Behaviour继承于 Component,所以Camera是组件


Camera 有哪些静态属性,用程序验证并管理所有的 Camera ,并在程序中 enabled 部分有用的 Camera (切换摄像机)

根据官方文档可查到,Camera的静态变量有以下:
* allCameras 返回所有可以使用的camera
* allCamerasCount 翻译场景中所有照相机的数量
* current 当前用于渲染的相机,只用于低级的渲染控制
* main 第一个被启用的Camera会被标记为main
* onPostRender 任何一个camera结束rendering都会触发的时间
* onPreCull 任何一个camera开始culling的时候触发的事件
* onPrerRender 任何一个camera在开始rendering之前都会触发的事件

使用程序来控制camera:

对象树如下:

这里写图片描述

控制代码如下:

using UnityEngine;
using System.Collections;

public class camera : MonoBehaviour {
    public Camera maincamera; 
    public Camera currentcamera;
    public Camera[] cameras;

    // Use this for initialization
    void Start () {
        print ("Cameralength = " + Camera.allCamerasCount); //输出camera数量
        maincamera = Camera.main; // 获取maincamera
        cameras = Camera.allCameras; // 获取所有的camera
        currentcamera = Camera.current; // 获取当前的camera
    }

    // Update is called once per frame
    void Update () {
        changeCamera ();
    }

    void changeCamera(){
        // 点击1,2,3切换canmera,注意3个camera必须在同一个display下
        if (Input.GetKeyUp (KeyCode.Alpha1)) {
            cameras [0].enabled = true;
            cameras [1].enabled = false;
            cameras [2].enabled = false;
        } else if (Input.GetKeyUp (KeyCode.Alpha2)) {
            cameras [0].enabled = false;
            cameras [1].enabled = true;
            cameras [2].enabled = false;
        } else if (Input.GetKeyUp(KeyCode.Alpha3)){
            cameras [0].enabled = false;
            cameras [1].enabled = false;
            cameras [2].enabled = true;
        } else if (Input.GetKeyUp (KeyCode.M)) {
            //点击M后,所有camera设为false,除了主摄像机以外
            cameras [0].enabled = false;
            cameras [1].enabled = false;
            cameras [2].enabled = false;
            maincamera.enabled = true;
        }

    }
}

添加一个 Empty 游戏对象, 添加一个 Camera 部件(Rendering 分类下),有什么效果

添加前:

这里写图片描述

添加后:

这里写图片描述

就已经是camera了,充分证明了camera的组件性质


光源用法总结

camera聚光灯

其实就是个camera添加light组件,light设为术光

这里写图片描述


给sun对象添加光源部分

使用light组件作为光源比用glew11更简单方便

这里写图片描述


没有将 Camera,Light 设计为 GameObject ,这给开发者带来哪些好处?

可以更方便的对对象进行使用,添加,修改。


面向对象语言接口和超类有哪些异同?

  • 接口是公开的,里面不能有私有的方法或变量,是用于让别人使用的,而抽象类是可以有私有方法或私有变量的
  • 实现接口的一定要实现接口里定义的所有方法,而实现抽象类可以有选择地重写需要用到的方法
  • 接口可以实现多重继承,而一个类只能继承一个超类

IU3dActionCompleted 能设计为超类吗?为什么? 画 UML 图说明

不能,因为一个类只能继承一个超类,所以U3dActions 不能继承 Monobehaviours的同时再继承一个IU3ActionsCompleted类


U3dAction 能设计为接口吗?为什么? 画 UML 图说明

不能设计为接口,因为接口是不能有自己的私有变量和函数实现的


修改简单工厂的代码

理清代码之后,添加一个新动作是非常容易的,只需要3步:

  • 首先判断这个动作是自动还是人控制的,然后创建这个动作的类 A 继承于 U3dActionAuto 或者 U3dActionMan,这个类里面的Update方法中写上你希望动作的执行方式
  • 在ActionManager中写一个和你这个新动作相匹配的 Apply…(…)
  • 在start()函数里添加该动作
  • 在接口函数中写上相应的动作结束的时候,应该执行的动作
添加一个新动作,MoveToTargetAction(持续追击一个目标)

在原来代码的基础上创建一个 gameObject,名字为zhui,然后zhui会以0.9的速度持续追击Cube

这里写图片描述


添加一个新动作,MoveToAB_Action (组合动作,就是将两个MoveTo动作组合成一个新动作,动作执行完,就free掉)

用新写的函数MoveToAB_Action取代之前的让cube来回移动的函数,在该函数里创建子动作并调用,用完后destroy掉。(这里不清楚要求的Free具体是什么意思,所以现在函数里面直接实现,明白的同学求指教下)


添加一个新动作,MoveToTargetAB_Action

这个和上一个唯一的不同在于是以两个对象为目标而不是两个position为目标的。其他写法如上

对象树如下:

这里写图片描述

代码如下:

using UnityEngine;
using System.Collections;
using Com.Mygame;

namespace Com.Mygame {
    public class ActionManager :System.Object {
        private static ActionManager _instance;

        public static ActionManager GetInstance(){
            if (_instance == null) {
                _instance = new ActionManager();
            }
            return _instance;
        }

        public U3dAction ApplyMoveToAction(GameObject obj, Vector3 target, int speed, IU3dActionCompleted completed){
            MoveToAction ac = obj.AddComponent <MoveToAction> ();
            ac.setting (target, speed, completed);
            return ac;
        }

        public U3dAction ApplyMoveToAction(GameObject obj, Vector3 target, int speed) {
            return ApplyMoveToAction (obj, target, speed, null);
        }

        public U3dAction ApplyMoveToAction(GameObject obj, GameObject obj2,float speed){
            MoveToTargetAction ac = obj.AddComponent<MoveToTargetAction> ();
            ac.setting (obj2, speed);
            return ac;
        }

        public U3dAction ApplyMoveToAB_Action(GameObject obj, Vector3 A, Vector3 B, int speed){
            MoveToAB_Action ac = obj.AddComponent<MoveToAB_Action>();
            ac.setting (A,B,speed,obj);
            return ac;
        }

        public U3dAction ApplyMoveToTargetAB_Action(GameObject obj,GameObject A,GameObject B,int speed){
            MoveToTargetAB_Action ac = obj.AddComponent<MoveToTargetAB_Action> ();
            ac.setting (A, B, speed, obj);
            return ac;
        }

    }
    public class U3dActionException : System.Exception {}

    public interface IU3dActionCompleted {
        void OnActionCompleted (U3dAction action);
    }

    public class U3dAction : MonoBehaviour {
        public void Free(){}
    }
    public class U3dActionAuto : U3dAction {}
    public class U3dActionMan : U3dAction {}

    public class MoveToAction :  U3dActionAuto {
        public Vector3 target;
        public int speed;

        private IU3dActionCompleted monitor = null;

        public void setting(Vector3 target, int speed, IU3dActionCompleted monitor){
            this.target = target;
            this.speed = speed;
            this.monitor = monitor;
        }

        void Update () {
            float step = speed * Time.deltaTime;
            transform.position = Vector3.MoveTowards(transform.position, target, step);

            if (transform.position == target) { // Auto Destroy After Completed
                if (monitor != null) {
                    monitor.OnActionCompleted(this);
                }
                Destroy(this);
            }
        }
    }

    public class MoveToTargetAction : U3dActionAuto {
        public GameObject target;
        public float speed;

        public void setting(GameObject target,float speed){
            this.target = target;
            this.speed = speed;
        }

        void Update() {
            float step = speed * Time.deltaTime;
            transform.position = Vector3.MoveTowards (transform.position, target.transform.position, step);

            if(transform.position == target.transform.position){
                // if get do nothing
            }
        }
    }

    public class MoveToAB_Action : U3dActionAuto {
        public Vector3 A;
        public Vector3 B;
        public int speed;
        public MoveToAction toA;
        public MoveToAction toB;
        public GameObject obj;

        public void setting(Vector3 A,Vector3 B,int speed,GameObject obj) {
            this.A = A;
            this.B = B;
            this.speed = speed;
            this.obj = obj;
        }

        void Start(){
            toA = obj.AddComponent<MoveToAction> ();
            toA.setting (A, speed, null);
        }

        void Update() {
            float step = speed * Time.deltaTime;
            if (obj.transform.position == A) {
                Destroy (obj.GetComponent("toA"));
                toB = obj.AddComponent<MoveToAction> ();
                toB.setting (B,speed,null);
            }
            if (obj.transform.position == B) {
                Destroy (obj.GetComponent("toB"));
                toA = obj.AddComponent<MoveToAction> ();
                toA.setting (A,speed,null);
            }

        }

    }

}


public class MoveToTargetAB_Action : U3dActionAuto {
    public GameObject A;
    public GameObject B;
    public int speed;
    public MoveToAction toA;
    public MoveToAction toB;
    public GameObject obj;


    public void setting(GameObject A,GameObject B,int speed,GameObject obj) {
        this.A = A;
        this.B = B;
        this.speed = speed;
        this.obj = obj;
    }

    void Start(){
        toA = obj.AddComponent<MoveToAction> ();
        toA.setting (A.transform.position, speed, null);
    }

    void Update() {
        float step = speed * Time.deltaTime;
        if (obj.transform.position == A.transform.position) {
            Destroy (obj.GetComponent("toA"));
            toB = obj.AddComponent<MoveToAction> ();
            toB.setting (B.transform.position,speed,null);
        }
        if (obj.transform.position == B.transform.position) {
            Destroy (obj.GetComponent("toB"));
            toA = obj.AddComponent<MoveToAction> ();
            toA.setting (A.transform.position,speed,null);
        }

    }

}

public class U3dActions : MonoBehaviour, IU3dActionCompleted {

    private GameObject cube;
    private GameObject x;
    private GameObject y;

    private GameObject zhui;

    public void OnActionCompleted (U3dAction action)
    {
        MoveToAction ma = action as MoveToAction;
        if (ma.target == x.transform.position) {
            ActionManager.GetInstance ().ApplyMoveToAction (cube, y.transform.position, 1, this);
        } else {
            ActionManager.GetInstance ().ApplyMoveToAction (cube, x.transform.position, 1, this);
        }
    }

    // Use this for initialization
    void Start () {
        cube = GameObject.Find ("Cube");
        x = GameObject.Find ("xx");
        y = GameObject.Find ("yy");
        zhui = GameObject.Find ("zhui");

        //ActionManager.GetInstance ().ApplyMoveToAction (cube, x.transform.position,1,this);

        // 以下这个是添加追击的方法
        ActionManager.GetInstance ().ApplyMoveToAction (zhui, cube, 0.9f);

        //以下是在两个坐标之间移动的方法
        //ActionManager.GetInstance ().ApplyMoveToAB_Action (cube,x.transform.position, y.transform.position, 1);

        //一下是在两个对象之间移动的方法
        ActionManager.GetInstance ().ApplyMoveToTargetAB_Action (cube, x, y, 1);
    }

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

    }
}

简单工厂的好处,还能再游戏中做什么?

通过工厂模式,外界可以从直接创建具体对象的局面中摆脱出来,只要负责消费就可以了。而且不比管这些对象究竟是如何创建及如何组织的,明确了各自的职责和权利,有利于整个软件体系结构的优化。

所以工厂模式,不仅可以对动作,还可以对对象,方便的创建对象和场景的简单工厂

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值