2017-04-11 20:05:26 Mogoson 阅读数 2117
  • Unity3D场景优化算法

    该课程主要是针对密集型场景裁剪处理提供了解决方案,利用四叉树或者八叉树对场景进行分割,然后通过角色身上的包围盒与四叉树或者八叉树分割的物体进行碰撞检测,这样就可以把玩家周围的物体显示出来,这个也是针对移动端的解决方案。如果对于PC端可以使用多线程分块解决,该课程也是给读者提供了一种场景优化的解决方案。

    122 人正在学习 去看看 姜雪伟

MGS-Map

概述

Unity3D 制作场景地图,地图轨迹 插件包。

方案

  • 计算小地图UI与场景地形的尺寸比例,获取地图标记的位置。
  • 计算地形上标记与世界方向的方向差,获取地图标记的方向。
  • 动态生成UI贴图,绘制地图标记运动轨迹。

实现

  • MapFlag.cs 地图标记,例如:漫游角色。
  • GlobalMap.cs 全局地图。
  • LocalMap.cs 局部地图。
  • FlagTrail.cs 地图轨迹。

源码

2015-03-10 10:02:51 book_longssl 阅读数 1318
  • Unity3D场景优化算法

    该课程主要是针对密集型场景裁剪处理提供了解决方案,利用四叉树或者八叉树对场景进行分割,然后通过角色身上的包围盒与四叉树或者八叉树分割的物体进行碰撞检测,这样就可以把玩家周围的物体显示出来,这个也是针对移动端的解决方案。如果对于PC端可以使用多线程分块解决,该课程也是给读者提供了一种场景优化的解决方案。

    122 人正在学习 去看看 姜雪伟

    


总的来看,Unity的使用场景主要有以下几个:

  • 建立类型映射
  • 用于单例模式
  • 用于依赖注入

接下来,将逐一介绍各使用场景。


       在创建对象时,毫无疑问,类型映射是我们无法回避的一个问题,同时也是一系列工厂模式的根本出发点。类型映射,为面向对象设计的根本原则——“针对接口编程,而不是针对实现编程”、“要依赖抽象,不要依赖具体类”——在应用中的实现,提供了有力的支持。

我们知道,Unity提供了对象的容器,那么这个容器是如何进行索引的呢?也就是说,容器内的单元是如何标识的呢?在Unity中,标识主要有两种方式,一种是直接使用接口(或者基类)作为标识键,另一种是使用接口(或者基类)与名称的组合作为标识键。键对应的值就是具体类。


  • 用接口类型作为标识键

      实际上,之前给出的例子,就是接口类型作为标识键的一个使用场景,这里就不再重复。

      这里需要指出的是,Unity提供的功能都有泛型和非泛型两个版本,这样可以确保 Unity 在不支持泛型的环境中使用。我们在代码中可以使用任意一种方法(泛型和非泛型),或者根据需要混合使用。例如,可以使用泛型形式来注册映射,然后使用非泛型形式去获取对象实例。

下面的代码演示了非泛型形式的使用:



ps:接下来的例子以及后续文章中的例子将不再演示非泛型形式的使用。

  • 用基类作为标识键

用基类作为标识键,在本质上与用接口类型作为标识键是一样的。这里需要注意的是,基类并不一定是指抽象类。下面是使用基类作为标识键的例子:




有趣的是,这里如果直接container.RegisterType();的话,是可以Resolve出来的,但是如果我们container.RegisterType();的话,运行时就会报异常了。

 

  • 用接口(或基类)与名称的组合作为标识键

如果需要使用同样的接口(或基类)注册多个映射,可以指定名称来区分每个映射。在需要Resolve的时候,通过指定接口(或基类)与名称的组合作为标识键,就可以获取恰当类型的对象。下面的例子以接口与名称的组合为例,基类与名称的组合作为标识键同理,不再赘述(有关Ilogger等代码:



这里需要指出的是,注册名称是一个字符串,如果需要,可以包含空格。它们是大小写敏感的。例如,名称“Mymapping”和“MyMapping”将指的是二个不同的注册映射。


2018-09-11 10:49:16 weixin_42513339 阅读数 1421
  • Unity3D场景优化算法

    该课程主要是针对密集型场景裁剪处理提供了解决方案,利用四叉树或者八叉树对场景进行分割,然后通过角色身上的包围盒与四叉树或者八叉树分割的物体进行碰撞检测,这样就可以把玩家周围的物体显示出来,这个也是针对移动端的解决方案。如果对于PC端可以使用多线程分块解决,该课程也是给读者提供了一种场景优化的解决方案。

    122 人正在学习 去看看 姜雪伟

在Unity3D中,一个场景在运行中切换到另一个场景的方法

1.  在Unity中 File->Build Settings->把要切换的场景添加到Scenes In Build下面,也可以Add Open Scenes,添加完关闭这个页面,不要点 Build 或者 Build And Run 。

2. 添加需要加转换场景的代码。

//首先要记得加上引用命名空间

using UnityEngine.SceneManagement;

//然后在需要的代码区域加上:

SceneManager.LoadScene("SceneName");//要切换到的场景名

或者

SceneManager.LoadScene(0); //数字不一定是0,括号里数字是场景的编号,这个编号就是在 File->Build Settings ,上方 Scene In Build,场景名字那行最右边的数字

2019-02-09 16:16:56 Jaihk662 阅读数 209
  • Unity3D场景优化算法

    该课程主要是针对密集型场景裁剪处理提供了解决方案,利用四叉树或者八叉树对场景进行分割,然后通过角色身上的包围盒与四叉树或者八叉树分割的物体进行碰撞检测,这样就可以把玩家周围的物体显示出来,这个也是针对移动端的解决方案。如果对于PC端可以使用多线程分块解决,该课程也是给读者提供了一种场景优化的解决方案。

    122 人正在学习 去看看 姜雪伟

 

前文:https://blog.csdn.net/jaihk662/article/category/8659261

一、场景分辨率

游戏场景分辨率设置

16:9常用分辨率有:1920*1080, 1280*720, 960*540, 720*405, 640*360, 320*180

有了场景之后,一般就可以开始先做UI了,新建 2D UI Root,调整分辨率自适应方法如下

      constraint:约束/限制

 

二、场景切换

先将所有需要用到的场景全部加入 Build Settings 的“打包面板”中

随意在场景1中的任何物体上挂载如下脚本:

SceneManager.LoadScene(string):切换到场景string(需要头文件UnityEngine.SceneManagement)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class SceneJump : MonoBehaviour
{
    void Start ()
    {
    }
    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.Space))
            SceneManager.LoadScene("Text2");
    }
}

这样当在场景1时,就可以通过按空格变换为场景2

 

 

2015-10-14 09:29:31 qinyuanpei 阅读数 7259
  • Unity3D场景优化算法

    该课程主要是针对密集型场景裁剪处理提供了解决方案,利用四叉树或者八叉树对场景进行分割,然后通过角色身上的包围盒与四叉树或者八叉树分割的物体进行碰撞检测,这样就可以把玩家周围的物体显示出来,这个也是针对移动端的解决方案。如果对于PC端可以使用多线程分块解决,该课程也是给读者提供了一种场景优化的解决方案。

    122 人正在学习 去看看 姜雪伟

  今天博主想和大家分享的是Unity3D场景编辑器的扩展开发,相关的话题我们在Unity3D游戏开发之编辑器扩展程序开发实例这篇文章中我们已经有所涉及,今天博主想特别针对场景编辑器的扩展开发来进行下深入研究。对于一个场景编辑器来说,它主要的作用是3D场景视图中实时显示、输入反馈和相关信息的更新。在Unity3D中提供了Editor、EditorWindow、GUILayout、EditorGUILayout、GUIUtility、EditorGUIUtility、Handles、Event等来完成这些工作。其中基于EditorWindow的这种扩展方式我们已经研究过了,这种扩展方式拥有自己的独立窗口使用OnGUI方法进行界面的绘制。今天我们想说的是基于Editor的这种扩展方式,这种扩展方式只能针对脚本,从脚本内容在Inspector里的显示布局到变量在Scene视图的可视化编辑,它都可以完全胜任。这里特别想说的是Handles和Event这两个类,这两个类分别提供了3D显示和输入反馈的功能,我们下面就来学习如何使用这些类来扩展Unity3D的场景编辑器。

创建一个扩展的Transform组件

  Transform是Unity3D中一个基本的组件,下面我们来创建一个扩展的Transform组件,该组件可以对游戏体的坐标、旋转、缩放进行重置。首先,我们创建一个ExtendTransform的类,该类继承自Editor类:

using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomEditor(typeof(Transform),true)]
public class ExtendTransform : Editor 
{
    /// <summary>
    /// Position属性
    /// </summary>
    private SerializedProperty mPos;

    /// <summary>
    /// Scale属性
    /// </summary>
    private SerializedProperty mScale;

    void OnEnable()
    {
        mPos = serializedObject.FindProperty("m_LocalPosition");
        mScale = serializedObject.FindProperty("m_LocalScale") ;
    }

    /// <summary>
    /// Inspector相关GUI函数
    /// </summary>
    public override void OnInspectorGUI()
    {
        EditorGUIUtility.labelWidth = 15;
        //获取最新的可序列化对象
        serializedObject.Update();
        //绘制物体的坐标、旋转和缩放
        DrawPosition();
        DrawRotate();
        DrawScale();
        //更新可序列化对象的属性
        serializedObject.ApplyModifiedProperties();
    }

    /// <summary>
    /// 绘制位置
    /// </summary>
    private void DrawPosition()
    {
        GUILayout.BeginHorizontal();
        {
            bool Reset = GUILayout.Button("P", GUILayout.Width(20f));
            EditorGUILayout.LabelField("Position");
            EditorGUILayout.PropertyField(mPos.FindPropertyRelative("x"));
            EditorGUILayout.PropertyField(mPos.FindPropertyRelative("y"));
            EditorGUILayout.PropertyField(mPos.FindPropertyRelative("z"));
            if(Reset) mPos.vector3Value = Vector3.zero;
        }
        GUILayout.EndHorizontal();
    }

    /// <summary>
    /// 绘制旋转
    /// </summary>
    private void DrawRotate()
    {
        Vector3 eulerAngles = ((Transform)target).eulerAngles;
        GUILayout.BeginHorizontal();
        {
            bool Reset = GUILayout.Button("R", GUILayout.Width(20f));
            EditorGUILayout.LabelField("Rotation", GUILayout.Width(70f));
            EditorGUILayout.LabelField("X", GUILayout.Width(13f));
            float angleX=EditorGUILayout.FloatField(eulerAngles.x, GUILayout.Width(56f));
            EditorGUILayout.LabelField("Y", GUILayout.Width(13f));
            float angleY = EditorGUILayout.FloatField(eulerAngles.y, GUILayout.Width(56f));
            EditorGUILayout.LabelField("Z", GUILayout.Width(13f));
            float angleZ = EditorGUILayout.FloatField(eulerAngles.z, GUILayout.Width(56f));
            ((Transform)target).eulerAngles = new Vector3(angleX, angleY, angleZ);
            if(Reset)
            {
                eulerAngles = Vector3.zero;
                ((Transform)target).eulerAngles = Vector3.zero;
            }
        }
        GUILayout.EndHorizontal();
    }

    /// <summary>
    /// 绘制缩放
    /// </summary>
    private void DrawScale()
    {
        GUILayout.BeginHorizontal();
        {
            bool Reset = GUILayout.Button("S", GUILayout.Width(20f));
            EditorGUILayout.LabelField("Scale");
            EditorGUILayout.PropertyField(mScale.FindPropertyRelative("x"));
            EditorGUILayout.PropertyField(mScale.FindPropertyRelative("y"));
            EditorGUILayout.PropertyField(mScale.FindPropertyRelative("z"));
            if (Reset) mScale.vector3Value = Vector3.one;
        }
        GUILayout.EndHorizontal();
    }
}

  首先我们注意到ExtendTransform继承自Editor,这是我们开发这类编辑器扩展的第一个前提。其次我们注意到在该类的声明位置有这样一个标记:

[CustomEditor(typeof(Transform),true)]

该标记表明我们这个编辑器扩展是针对Transform组件进行扩展的,即当物体存在Tranform组件时会在编辑器中响应这个编辑器扩展程序。我们在这个编辑器扩展程序中都做了哪些事情呢?第一,我们实现了OnEnable()方法,该方法相当于一个初始化的方法;第二,我们重写了OnOnInspectorGUI()方法,该方法将覆盖默认的Inspector窗口外观。

扩展后的Transform

好了,现在我们点击场景中默认的相机MainCamera可以发现默认的Transform会变成具有重置功能的扩展型Transform。下面我们来介绍这段程序中较为重要的核心内容:

Unity3D中的可序列化对象

  通常我们所说的序列化是指将一个对象的实例转化为字符串的过程,而在Unity3D中可序列化对象更像是一种智能对象,它可以将脚本中的属性显示在Inspector窗口中,当场景发生变化时这些属性值将自动被更新。例如我们可以定义这样一个简单的脚本:

/// <summary>
/// 定义一个可序列化类
/// </summary>
[System.Serializable]
public class ExampleClass 
{
    [SerializeField]
    public int ID;
    [SerializeField]
    public string Name;
    [SerializeField]
    public Vector3[] Points;

    private bool editable = false;
}

/// <summary>
/// 定义一个简单的脚本
/// </summary>
public class ExampleScript : MonoBehaviour 
{
    public ExampleClass Example;
}

此时如果我们给场景中的某个物体附加上该脚本,则我们在Inspector窗口可以看到Example类的实例Example将被序列化到编辑器面板中,同时我们可以注意到私有的editable字段并没有被序列化出来,这是因为在Unity3D中,公有的字段默认支持序列化,私有的字段除非显式的增加[SerializeField]标记,否则都不会被序列化,这一点希望大家注意。好了,那么我们为什么要讲这部分内容呢,这是因为它和我们下面要讲的Editor基类中的属性和方法有着十分密切的关联。

Unity3D中的可序列化对象

Editor基类中的属性和方法

  Editor基类中有两个重要的属性,即target和serializedObject。target表示当前受检查的物体我们可以通过它获得当前物体;而serializedObject表示当前物体的全部可序列化信息,我们可以通过它获得指定的序列化字段及其数值。Editor基类中重要的方法有:
* OnInspectorGUI():该方法可对Inspector窗口面板进行扩展或者重写,比如我们可以通过DrawDefaultInspector()方法来绘制默认Inspector窗口面板然后在此基础上使用GUILayout或者EditorGUILayout等辅助类进行自定义的绘制。在这个示例中我们对整个面板进行了重写,值得注意的是为了让Inspector窗口面板正常工作,如果要重绘该窗口请确保对该方法进行覆盖。
* OnSceneGUI():该方法可对场景视图进行绘制,在实际的使用中可以配合Handles类和Event类来进行网格编辑、地形绘制或高级Gizmos等方面的工作。在本文的第二个示例中,我们将利用这一特性来编写一个用于NPC寻路的路径节点编辑工具。

对第一个示例的总结

  在第一个示例中,可以注意到我们使用了FindProperty()方法来获取一个可序列化物体的属性(字段),然后我们在EditorGUILayout.PropertyField()方法来绘制了各种属性框,这种方式可以实现属性的自动更新。注意到DrawRotate()方法与DrawPositin()及DrawScale()方法在实现方式上略有不同,这是因为Transform组件的Rotation属性是一个Quaternion即四元数的结构,四元数是利用x、y、z、w四个数值来表示物体的三维旋转,这不仅和我们平时习惯的欧拉角相违背而且更为关键的是貌似目前我还没有发现可以直接绘制四元数的API接口,如果有的话希望大家可以告诉我,所以这里我们用了变通的一种方法,即通过Transform的eulerAngles来实现,但是这种方式绘制的属性框大小和EditorGUILayout.PropertyField()方法绘制的属性框大小并不一致,同时我们需要自己去完成属性值的更新。好了,暂时先总结到这里更多的细节大家可以通过代码来了解。

创建一个NPC寻路节点编辑工具

  创建这样一个工具的想法来自我实际的工作体验,当我Unity3D中使用的Tween动画库从iTween变成Dotween后,我在使用Dotween的过程中一直没有找到类似于iTweenPath的路径节点编辑工具。作为一个有节操的程序员,去寻找破解版的Dotween Pro这样的事情我是能不干就不干啦,因为我觉得自己有能力做这样一个类似的小工具,所以在一边准备这篇文章的时候,一边开始设计这样一个路径节点编辑工具。相信经过第一个示例的铺垫和相关知识的储备,大家都了解了这些内容,所以这里直接给出代码啦,因为实在是没有多少内容,嘿嘿:

using UnityEngine;
using System.Collections;
using UnityEditor;

[CustomEditor(typeof(PatrolNPC))]
public class PatrolPathEditor : Editor 
{
    /// <summary>
    /// 寻路节点
    /// </summary>
    private Vector3[] paths;

    /// <summary>
    /// 显示寻路信息的GUI
    /// </summary>
    private GUIStyle style=new GUIStyle();

    /// <summary>
    /// 初始化
    /// </summary>
    void OnEnable()
    {
        //获取当前NPC的寻路路径
        paths = ((PatrolNPC)target).Paths;
        //初始化GUIStyle
        style.fontStyle = FontStyle.Normal;
        style.fontSize = 15;
    }


    void OnSceneGUI()
    {
        //获取当前NPC的寻路路径
        paths = ((PatrolNPC)serializedObject.targetObject).Paths;
        //设置节点的颜色为红色
        Handles.color = Color.red;
        if(paths.Length <= 0 || paths.Length<2) return;
        //在场景中绘制每一个寻路节点
        //可以在场景中编辑节点并将更新至对应的NPC
        for (int i = 0; i < paths.Length; i++)
        {
            paths[i] = Handles.PositionHandle(paths[i], Quaternion.identity);
            Handles.SphereCap(i, paths[i], Quaternion.identity, 0.25f);
            Handles.Label(paths[i], "PathPoint" + i, style);
            if (i < paths.Length && i + 1 < paths.Length)
            {
                Handles.DrawLine(paths[i], paths[i + 1]);
            }
        }
    }

}

  这里的PatrolNPC是一个可寻路NPC类,基本和这篇文章的内容无关,大家只要知道那个Paths字段是一个Vector3[]就好啦,这样当我们在场景中编辑这些路径节点的时候,对应NPC的路径节点信息就会同步发生更新,这样我们就可以随心所欲地规划NPC的移动路径啦,哈哈。好了,今天的内容就是这样啦,写完熬到这个点真心不容易啊,大家晚安,这是这个小工具在场景编辑器中的效果,嘻嘻,感觉还是蛮不错的吧,反正我是很喜欢就对啦!

路径节点编辑工具演示

Unity3D_场景の烘培

阅读数 26544

Unity3D 5.1烘培

阅读数 29270

没有更多推荐了,返回首页