Unity各种小技巧函数方法—RPG黑暗之光解析

修改游戏中的默认鼠标图标:

File->BuildSettings->PlayerSettings:中的Defult Cursor,
将你要使用的图标图片拖动到Defult Cursor中即可;


给场景添加天空盒子:

首先需要需要Main—Camera中的Clear Flags选为:Skybox,然后为MainCamera Add Component一个Skybox,修改其中的Custom Skybox材质;


实现镜头的缓慢拉近效果:
首先定义一个float 类型的值(沿着哪方向改变的就定义哪个方向上的终点值),用translate方法强行改变摄像机的坐标就可以了。
void Update()
{
  if(transform.position.z<endZ)
   {
       transform.translate(Vector3.forword*speed*Time.deltaTime);
   }
}



使用NGUI和白色图片给场景添加渐显效果:

首先在UIroot下创建一个Texture,为此Textrue添加Tween Alpha透明度动画,改变其From 和to 的值即可,如果运行后没有效果,可以修改Tweener中的StartDelate 的值,


处理任何按键按下的事件:
首先定义一个bool 类型的
 isAnyKeyDown = falsel;
void Update()
{
    if(isAnyKeyDown == false)
    {
        if(Input.anyKey)
        {
         // 添加事件;在事件中处理isAnyKeyDown = true;
        }
    }
}
Input.anyKey:任意键,bool类型。检测是否某一按键杯按住。


关于在脚本中查找物体:
1.通过检视面板指定参数:
可以吧参数显示在检视面板上面,然后拖拽游戏对象到检视面板中的target位置

2.使用tranform.Find 方法寻找所有的子物体。 
按名字查找物体的话,this.transform.parent.Find("")其寻找的是同级的,寻找同级需要先找到同级的父物体,然后在父物体下查找同级。

3.指定名字或者标签。
通过名字:GameObject.Find("名字");
通过标签:GameObject。FInWithTag("Tag");

PlayerPrefs:玩家偏好,
在游戏会话中储存和访问玩家偏好设置。可以当做全局变量来使用。
Class Functions类函数:
  • SetInt :
    static function SetInt (key : string, value : int) : void  
    Sets the value of the preference identified by key.
    设置由key确定的偏好值。

  • GetInt :
    static function GetInt (key : string, defaultValue : int = 0) : int
    Returns the value corresponding to key in the preference file if it exists.
    如果存在,返回偏好文件中key对应的值。

  • SetFloat:
    static function SetFloat (key : string, value : float) : void
    Sets the value of the preference identified by key.
    设置由key确定的偏好值。

  • GetFloat:

    static function GetFloat (key : string, defaultValue : float = 0.0F) : float

    Returns the value corresponding to key in the preference file if it exists.
    如果存在,返回偏好文件中key对应的值。如果不存在,将返回默认值;

  • SetString:
    static function SetString (key : string, value : string) : void
    Sets the value of the preference identified by key.
    设置由key确定的偏好值。
  • GetString:

    static function GetString (key : string, defaultValue : string = "") : string

    Returns the value corresponding to key in the preference file if it exists.
    如果存在,返回偏好文件中key对应的值。
  • HasKey:

    static function HasKey (key : string) : bool

    Returns true if key exists in the preferences.
    如果key在偏好中存在,返回true。
  • DeleteKey:

    static function DeleteKey (key : string) : void

    Removes key and its corresponding value from the preferences.
    从偏好中删除key和它对应的值。 
  • DeleteAll:

    static function DeleteAll () : void

    Removes all keys and values from the preferences. Use with caution.
    从偏好中删除所有key。请谨慎使用。 

    控制所有角色的显示和控制:
    首先定义一个Prefabs 的数组,用来存储要实例化的游戏角色,然后定义一个数组用来存储实例化出来的角色对象。
    在Start函数中赋值:
    public GameObject[] characterPrefabs;
    private GameObject[] characterGameObjects;
    private int length;
    void Start()
    {
    length = characterPrefabs.Length;
    for(int i = 0;i<lengh;i++)
    {
    characterGameObjects[i] = GameObject.Instantiate(characterPrefabs[i],tranform.position,tranform.rotation) as GameObject;
    }

    储存游戏创建时的角色名称:用PlayerPrefs偏好设置。

    Tag管理类:public const string ground= "Ground",用const来设置这是一个共有 的不可变的变量,不可修改。

    实例化行走时的点击效果:
    首先定义出我们实例化的Prefab;
    添加以下代码:
    public GameObject effect_click_prefab;

    void Update()
    {
    if(Input.GetMouseButtonDown(0))    //获取鼠标左键的按下,
    {
    Ray ray = Camera.main.ScreenPointToRay(INput.mousePosition);  //将鼠标的按下时的点转化为一条射线,
    RaycastHit hitInfo;                                                          //射线的信息。
    bool isCollider = Physics.Raycast(ray,out hitInfo);                     //标记是否检测到了碰撞,
    if(isCollider && hitInfo.collider.tag == Tags.ground)    //如果点击的是地面。
    {
    ShowClickEffect(hitINfo.point);                                       //调用相应的函数,实例化Prefab;
    }
    }
    }
    void ShowClickEffect(Vector3 hitPoint)
    {
    GameObject.Instantiate(effect_click_prefab,hitPoint,Quaternion.identity);  //实例化,Quaternion.identity:恒等式旋转,

    返回恒等式旋转(只读)。这个四元数对于“无旋转”:这个物体完全对齐于世界或父轴。

    }

    将目标朝向点击鼠标的位置:
    首先我们要获取到鼠标在屏幕上的点击位置,然后让主角的position和鼠标点击位置的position在Y轴上保持一致,只需要利用tranform.LookAt()函数改变主角的X,Z的即可;
    简短的代码:
    targetPosition = new Vector3(targetPosition.x,tranform.postion.y,targetPosition.z);
    this.tranform.LookAt(targetPosition);

    控制主角移动动画的播放:
    首先要让主角这个gameobject上有Animation组件,然后将主角的所有动画都拖动到Animation组件的Animations属性上,为Animation组件的Animation参数添加默认的Idle动画。
    然后我们可以在PlayerMove脚本中定义一个枚举类型的PlayerState:Moving,Idle;
    我们可以创建一个PlayerAnimation的脚本来控制主角的动画播放、然后使用Aimation.CrossFade:淡入淡出,(此函数在一定时间内淡入淡出名称为name的动画,并且淡出其他动画)
    Aimation.CrossFade:淡入淡出,

    function CrossFade (animation : string, fadeLength : float = 0.3F, mode : PlayMode = PlayMode.StopSameLayer) : void

    此函数在一定时间内淡入淡出名称为name的动画,并且淡出其他动画。

    如果模式是PlayMode.StopSameLayer,在同一层的动画将在动画淡入的时候淡出。如果模式是PlayMode.StopAll,所有动画将在淡入的时候淡出。

    If the animation is not set to be looping it will be stopped and rewinded after playing. 
    如果动画没有被设置成循环,它将停止并且在播放完成之后倒带至开始。


    控制相机对主角的跟随:
    首先我们在Start方法中要让相机LookAt主角,并计算出刚开始时的偏移量,在Update中跟据刚开始时的偏移量,以后每一帧都让摄像机的位置 =  Player加上这个偏移量;
    void Start()
    {
    tranform.LookAt(Player.Position);
    offestPosition = tranform.position - Player.position;
    }
    void Update()
    {
    tranform.position = offestPosition +Player.position;
    }

    使用鼠标滑动控制相机的拉近和拉远效果;
    我们只需在Update中调用一个这个功能的函数就行了。
    思路:在得到鼠标滑动的信息后,改变相机和主角的位置便偏移值就行了。
    void ScrollView()
    distance = offestPosition.magniyude;   //首先计算相机和主角的距离值。
    distance += Input.GetAxis("Mouse ScrollWheel")*scrollSpeed;     通过滑动的信息来改变此距离值,
    offestPosition = offestPositipn.normalized *distance ;     在将此距离值化为主角和相机的偏移向量,这样相机的位置就会改变,视野也会改变。
    }
    上面这个拉近和拉远还是存在问题,我们必须要给拉近拉远效果一个判断,不要让它超过临界值,不然会出现Bug;

    鼠标控制视野的左右和上下旋转:
    我们在Carmera上添加一个脚本函数:
    void RotateView()
    {
    if(INput.GetMouseButtonDown(1))
    {
    isRotating = true;
    }
    if(Input.GetMouseButtonUp(1))
    {
    isRotating = false;
    }
    if(isRotating)
    {
    trannsform.RotateAround(player.position,Vector3.up,rotateSpeed*Input.GetAxis("Mouse X"));  //左右旋转,
    Vector3 originalPos = tranfrom.position;                        //我们记录下左右旋转后的位置和角度
    Quaternion originalRotastion = tranform.rotation;
    tranform.RotateAround(player.position,tranform.right,-rotateSpeed*Input.GetAxis("Mouse Y")); //上下旋转, //影响的属性有两个,position,rotation。
    float x= tranform.euerAngles.x;                
    if(x<10||x>80)
    {
    tranform.position.= originalPos;
    tranform.rotation = originalRotation;   //如果上下旋转(绕着X轴)到边界,我们将属性归位原来的,就是让旋转无效
    }
    }
    offsetPosition = tranform.position  - player.position;
    }
    :注意:我们在使用Unity自带的RotateAround:

    function RotateAround (point : Vector3, axis : Vector3, angle : float) : void

    按照angle度通过在数世界坐标的point轴旋转物体。

    简单的说,按照多少度在世界坐标的某位置旋转物体;

    时需要让摄像机按照目标为旋转点,在旋转过后一定要记得更新摄像机和目标人物的差值。

    如果我们在Update函数中使用拉近拉远函数和旋转视野函数,我们需要把RotateView函数放在前面。因为在RotateView函数中会改变offsetPosition的朝向,ScrollView会改变offsetPosition的值,如果先调用ScrollView后调用RotateView会造成offsetPostion被重置。


    关于如何在点击UI控件时不让角色运动:

    我们在点击UI控件如:button时会遇到主角移动的Bug,其实这个问题很好解决,我们只需加一个判断就ok了,:if(UICamera.hoveredObject== null):这个判断是当前位置下是否有UI控件。


    在主场景中我们如何处理鼠标在collider上的事件:
    OnMouseOver()函数是Unity自带的脚本函数,我们党鼠标位于这个collider上的时候没回在每一帧调用这个方法。
    我们只需要在这个函数里面处理事件的相应和处理。

    当鼠标位于NPC上的时候改变鼠标的图标:
    public Textrue2D cursor_normal;
    public Textrue2d cursor_talk;

    private Vector2 hotspot = Vector2.zero;
    private CursorMode mode = CursorMode.Auto;
    public void SetNormal()
    {
    Cursor.SetCursor(cursor_normal,hotspot,mode);
    }
    public void SetNpcTalk()
    {
    Cursor.SetCursor(cursor_talk,hotspot,mode);
    }
    然后做成单例模式在OnMouseOver调用SetNpcTalk方法,在OnMouseExit调用SetNormal方法就ok了;hotspot是把那个位置的鼠标的点作为有效点击点,mode是模式。是软件修改还是系统修改图标。

    功能按钮的点击事件监听:
    添加Box Cillder,我们需要在UIButton脚本(Unity自带,只需要给物体添加上就行了)OnClick将处理放置处理点击事件的脚本的物体拖动进去,然后选择函数方法就行了,至于把处理相应事件的脚本放在哪里,最好放在它的父物体或者摄像机上比较靠谱,当然这个视情况而定,


    实现读取Text文本,并存在字典里,方便根据ID查找信息的方法实现:
    public TextAsset objectsInfoListText;
    void ReadInfo()
    {
    string text = objectsInfoListText.text;
    string[] strarray = text.Split('\n');
    foreach(string str in strArray)
    {
    string[] proArray = str.Split(',');
    ObjectInfo info = new ObjectINfo();
    int id = int.Parse(proArray[0]);
    string name = proArray[1];
    }
    }
    创建一个字典的话,首先需要加入头文件:using System.Collections.Generic;
    private Dictionary<int,ObjectInfo> objectInfoDict = new Dictionary<int,ObjectInfo>();

    加入字典:objecyInfoDict.Add(id,info);//添加到字典中,id为key,info为信息,可以很方便的根据id很方便的查找到信息。

    关于继承时候的Start和Update函数的使用:
    在及成果后的类里面,我们需要先执行父类里面的Start和Update(如果用到的话,)函数,Base.Start(),Base.Update();然后再写自身类里面的代码。

    如何让物品在物品栏里可以拖动:
    首先,我们需要给每个物品的格子添加BoxCollider,然后让管理物品的脚本继承自UIDragDropItem,如果需要处理拖动后的事件:protected override void OnDragDropRelease(GameObject surface)
    {
    base.OnDragDropRelease(surface);//先调用父类的函数,防止掩盖。
    }


    在物品栏里产生物品:
    NGUIToos.AddChild( , )它有连个参数,第一个是父物体,第二个是Prefab。
    如果拖动后让物品位于物品栏格子的中心:
    我们需要设置子物体相对于父物体的位置就可以了。设为0;
    transform.localPosition = Vector3.zero;


    如果物品加1,如何让物品栏格子的下标加1:
    首先int 类型的num+1;让后让numLabel.text = this.num.ToString();

    实现物品的拖拽功能:
     protected override void OnDragDropRelease(GameObject surface) {
            base.OnDragDropRelease(surface);
            if (surface != null) {
                if (surface.tag == Tags.inventory_item_grid) {//当拖放到了一个空的格子里面
                    if (surface == this.transform.parent.gameObject) {//拖放到了自己的格子里面

                    } else {
                        InventoryItemGrid oldParent = this.transform.parent.GetComponent<InventoryItemGrid>();   //得到老的方格。

                        this.transform.parent = surface.transform; ResetPosition();                        //将这个物品放在接触到的(surface)下面,并且让相对位置归位,
                        InventoryItemGrid newParent = surface.GetComponent<InventoryItemGrid>();  //得到新的父类,
                        newParent.SetId(oldParent.id, oldParent.num);                                     //在新的父类下面产生出一个一样的物品出来
     
                        oldParent.ClearInfo();                       //并且清除老格子的信息。
                    }

                } else if (surface.tag == Tags.inventory_item) {//当拖放到了一个有物品的格子里面,就交换两个格子里面的信息就行了。
                    InventoryItemGrid grid1 = this.transform.parent.GetComponent<InventoryItemGrid>();
                    InventoryItemGrid grid2 = surface.transform.parent.GetComponent<InventoryItemGrid>();
                    int id = grid1.id; int num = grid1.num;
                    grid1.SetId(grid2.id, grid2.num);
                    grid2.SetId(id, num);
                } else if (surface.tag == Tags.shortcut) {//拖到的快捷方式里面
                    surface.GetComponent<ShortCutGrid>().SetInventory(id);
                }

            }

            ResetPosition();
        }
    思路:物品交换的思路中的来说,先判断格子里是否有物品,如果没有,就在这个格子里面产生一个此物品就行了,如果放在了有物品的格子里面,如果物品相同,就让num+1;如果物品不同,就交换位子,即交换两个格子里面的物品信息显示就行了。

    显示物品的基本信息:
    首先我们给物品添加:,首先让物品上有Box Collider,添加UIEvent Listener脚本和UIEvent Trigger,然后我们可以在管理物品的脚本中写一个函数方法,拖到到OnHoberOver等事件监听的回调函数中,选择相应的方法就行了。

    如何让物品信息显示框跟随鼠标移动:
    我们让lable 的transform.position  = UICamea.currentCamera.ScreenToWorldPoint(INput.MousePosition);
    UICarmera.currentCamera是找到我们的UICamera的,然后根据ScreenToWorldPoint将鼠标的坐标转化为世界坐标。


    解决TextAsset文件读取Bug:
    首先将文本用记事本打开,点击另存为:当前路径,编码设置为UTF-8,保存覆盖。

    添加头像:
    我们在任务下面添加一个摄像机,然后添加一个Player层,将player的Layer层设置为Player,然后将相机的Culling Mask设置为Player,然后我们在工程视图中创建一个Render Texture。 然后将此摄像机的Target Texture设置为此Render Texture。然后在右上角添加产生一个simple Texture,然后将前面创建的render texture指定过来,然后调整就行了,我们先导入一个Shader资源,然后创建一个Material,将Material的shader制定,然后指定Render Texture和Shader材质,然后为相机的Material 指定为这个。

    小地图制作:
    过程同添加头像一样;

    设置NPC在小地图上的标识:
    首先我们在NPC下创建一个Quad,然后为其添加图片,将Quad调整方位和大小到NPC的正上方,然后添加一个NPC层,设置Main Carmera不渲染NPC层,显示小地图
    的相机渲染NPC层,当然要记得改变NPC的Layer;

    实现小地图上的拉近和拉远:
    我们在小地图的UI上创建两个Button按钮,为其添加脚本和方法,放在BUtton 的回调函数中,改变显示小地图的摄像机的orthographicSize的值;
    放大就--,缩小就++;

    显示MIss效果:
    我们需要导入HDUText资源包,然后里面有一个HduText的Prefab,我们先为每一个需要的物体下增加一个HudText我们需要在产生它的时候调用自带方法:
    HudText.Add("Miss",Color.gray,1);显示文字,文字颜色,显示时间;
    当然前提还有很多准备工作,此处就不提了。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值