脚本批量打包渠道包研究

最近在研究Unity3D脚本批量打包,比如在Android平台下各种不同分辨率和不同内存大小的机器,可能还有不同的渠道包,不同渠道可能用的SDK都不一样,这一切的一切都表明你的代码无法做到自适应的,除非批量打包提供各个平台的预定义标签#define

Unity默认提供了一些预定义标签如:

UNITY_EDITOR : 编辑器模式下。

UNITY_STANDALONE:PC Mac Linux模型下。

UNITY_IPHONE:IOS模式下。

UNITY_ANDROID:ANDROID模式下。

还有很多预定义标签、大家可以在这里看到:http://docs.unity3d.com/Documentation/Manual/PlatformDependentCompilation.html

官方提供的标签属于比较大的范围标签,比如我希望在UNITY_ANDROID下面在写一些自定义的标签、类似 QQ UC
CMCC这样的渠道标签该如何呢?如下图所示,ProjectSetting打包界面每个平台都会有Scripting Define
Symbols这个选项,可以在这里添加每个平台下对应的自定义标签(多个标签用“;”号隔开),这里我设置的是Android平台,如果IOS也需要打这样的渠道标签那么也要在IOS页面Scripting
Define Symbols选项处添加对应的标签。

标签做出来了就好办了,然后在代码中我们可以这样来写。如果在Scripting Define Symbols中没有出现的标签默认是不启用的,就像

#define Test 一样,会自动被注释掉。

然后我们看看如何实现脚本批量打包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;
public class MyEditorScript
{

//得到工程中所有场景名称
static string[] SCENES = FindEnabledEditorScenes();

//一系列批量build的操作

[MenuItem("Custom/Build Android QQ")]
static void PerformAndroidQQBuild()

{

BulidTarget("QQ", "Android");
}

[MenuItem("Custom/Build Android UC")]
static void PerformAndroidUCBuild()
{
BulidTarget("UC", "Android");
}

[MenuItem("Custom/Build Android CMCC")]
static void PerformAndroidCMCCBuild()
{
BulidTarget("CMCC", "Android");
}

[MenuItem("Custom/Build Android ALL")]
static void PerformAndroidALLBuild()
{
BulidTarget("QQ", "Android");
BulidTarget("UC", "Android");
BulidTarget("CMCC", "Android");
}

[MenuItem("Custom/Build iPhone QQ")]
static void PerformiPhoneQQBuild()
{
BulidTarget("QQ", "IOS");
}

[MenuItem("Custom/Build iPhone QQ")]
static void PerformiPhoneUCBuild()
{
BulidTarget("UC", "IOS");
}

[MenuItem("Custom/Build iPhone CMCC")]
static void PerformiPhoneCMCCBuild()
{
BulidTarget("CMCC", "IOS");
}

[MenuItem("Custom/Build iPhone ALL")]
static void PerformiPhoneALLBuild()
{
BulidTarget("QQ", "IOS");
BulidTarget("UC", "IOS");
BulidTarget("CMCC", "IOS");
}

//这里封装了一个简单的通用方法。
static void BulidTarget(string name, string target)
{
string app_name = name;
string target_dir = Application.dataPath + "/TargetAndroid";
string target_name = app_name + ".apk";

BuildTargetGroup targetGroup = BuildTargetGroup.Android;
BuildTarget buildTarget = BuildTarget.Android;

string applicationPath = Application.dataPath.Replace("/Assets", "");
if (target == "Android")
{
target_dir = applicationPath + "/TargetAndroid";
target_name = app_name + ".apk";
targetGroup = BuildTargetGroup.Android;
}

if (target == "IOS")
{
target_dir = applicationPath + "/TargetIOS";
target_name = app_name;
targetGroup = BuildTargetGroup.iPhone;
buildTarget = BuildTarget.iPhone;
}

//每次build删除之前的残留
if (Directory.Exists(target_dir))
{
if (File.Exists(target_name))
{
File.Delete(target_name);
}
}
else
{
Directory.CreateDirectory(target_dir);
}

//==================这里是比较重要的东西=======================
switch (name)
{
case "QQ":
PlayerSettings.bundleIdentifier = "com.game.qq";
PlayerSettings.bundleVersion = "v0.0.1";
PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, "QQ");
break;
case "UC":
PlayerSettings.bundleIdentifier = "com.game.uc";
PlayerSettings.bundleVersion = "v0.0.1";
PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, "UC");
break;
case "CMCC":
PlayerSettings.bundleIdentifier = "com.game.cmcc";
PlayerSettings.bundleVersion = "v0.0.1";
PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup, "CMCC");
break;
}

//==================这里是比较重要的东西=======================
//开始Build场景,等待吧~
GenericBuild(SCENES, target_dir + "/" + target_name,
buildTarget, BuildOptions.None);
}
private static string[] FindEnabledEditorScenes()
{
List<string> EditorScenes = new List<string>();
foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
{
if (!scene.enabled) continue;
EditorScenes.Add(scene.path);
}
return EditorScenes.ToArray();
}

static void GenericBuild(string[] scenes, string target_dir,
BuildTarget build_target, BuildOptions build_options)
{
EditorUserBuildSettings.SwitchActiveBuildTarget(build_target);
string res =
BuildPipeline.BuildPlayer(scenes, target_dir, build_target, build_options);
if (res.Length <= 0)
{
throw new Exception("BuildPlayer failure: " + res);
}
}
}{

这里面忘说了一点,如果我们希望在性能高的手机上用一套好的资源,在性能低的手机上用一套差一点的资源该怎么办?那么首先我们先搞清楚Unity会把什么资源打包,什么资源不打包?

1.Resources文件夹

Resources文件夹是一个只读的文件夹,通过Resources.Load()来读取对象。因为这个文件夹下的所有资源都可以运行时来加载,所以Resources文件夹下的所有东西都会被无条件的打到发布包中。建议这个文件夹下只放Prefab或者一些Object对象,因为Prefab会自动过滤掉对象上不需要的资源。举个例子我把模型文件还有贴图文件都放在了Resources文件夹下,但是我有两张贴图是没有在模型上用的,那么此时这两张没用的贴图也会被打包到发布包中。假如这里我用Prefab,那么Prefab会自动过滤到这两张不被用的贴图,这样发布包就会小一些了。

2.StreamingAssets

StreamingAssets文件夹也是一个只读的文件夹,但是它和Resources有点区别,Resources文件夹下的资源会进行一次压缩,而且也会加密,不使用点特殊办法是拿不到原始资源的。但是StreamingAssets文件夹就不一样了,它下面的所有资源不会被加密,然后是原封不动的打包到发布包中,这样很容易就拿到里面的文件。所以StreamingAssets适合放一些二进制文件,而Resources更适合放一些GameObject和Object文件。StreamingAssets
只能用过www类来读取!!

3.
最后凡是在Hierarchy视图对象引用过的资源文件也会被无条件打包到发布包中。如果有一部分文件可能没有在Resources文件夹下也没有在StreamingAssets文件夹下,也没有被Hierarchy视图游戏对象引用,那么这类资源是不会被打包到发布包中的。

OK!搞清楚这一点就好办了!在处理不同包对应不同资源包的时候,尽量让可配置的资源放在Resources
或StreamingAssets文件夹下,运行的时候程序动态的来读取它们,最后显示在游戏中就可以了。在批量打包前,在Project视图下创建不同包的资源文件夹,
然后脚本 AssetDatabase 动态的将资源拷贝至Resources或StreamingAssets 文件夹中,

http://docs.unity3d.com/Documentation/Manual/StreamingAssets.html

1
2
3
4
5
6
7
8
[MenuItem("Custom/Build Android QQ")]
static void PerformAndroidQQBuild()
{
//先把资源拷贝到Resources或者StreamingAssets
AssetDatabase.CopyAsset("path", "newPath");
//然后开始编译版本
BulidTarget("QQ", "Android");
}

代码中说到还有一个重要的东西就是PlayerSettings类。因为在Build的时候不同平台下可能会有一些PlatformSettings是不一样的,所以需要在脚本里面动态的设置它,强大的参数列表在这里:http://docs.unity3d.com/Documentation/ScriptReference/PlayerSettings.html。根据情况来批量构建自己的工程吧~

另外,由于IOS工程比较特殊,使用这样的方法我们只能生成出来多个IOS的工程文件,但是这并不是最终发布的版本。如果想一键生成.ipa文件的话。

1.通过命令行来Build
IOShttp://docs.unity3d.com/Documentation/Manual/CommandLineArguments.html

2.通过shell来自动打包 1生成的xcode工程,最终生成渠道包。

这两种方法我已经在网上找到了答案,今天太晚了就不在研究了,下一篇的时候我在补上。 祝大家学习愉快!!不早了,晚安!欢迎大家一起来讨论与学习,嘿嘿!!!

代码下载地址:http://vdisk.weibo.com/s/HUf2W

Unity5开发Oculus项目入门范例

今天为大家介绍使用Unity 5开发Oculus项目的入门范例Oculus Sample
Framework,该范例由Oculus制作,是为VR开发者和设计师提供的实验性示例集合。

其中包含了一系列的解决VR典型问题的示例场景,有第一人称视角的运动机制和基于注视的交互界面。每个范例都提供了在应用内调整参数的控制面板,这些参数包括传送过程中从透明到消失的时长,界面控制元素的延迟或瞄准器的Z深度等。该控制面板本身就很好的展示了VR中的控制器,可以直接将其用于自己的VR项目。

项目中的每个场景都展示了一个与VR开发相关的概念。整个范例是一个Unity 5 的项目。可以在Windows平台上执行,并且可以在Gear VR
Concepts
商城免费下载。这个应用可以让使用者在不打开Unity编辑器的情况下深入到场景中理解一些VR开发的概念。每个VR场景中都包含一份文档,所以可以深入到VR场景中直接学习。

如果想要深入探索并实现示例内的VR操作界面没有提供的功能,建议在Unity中打开并编辑该项目。

示例的主要作用是提供一套探索VR设计概念的工具,并非推荐大家都这么做。每个示例都包含了可供测试的游戏机制,其中有些设置会让玩家产生不适感,这是我们设计VR时需要避免的。这些功能的主要用途就是让开发者体验到什么是可行的,什么是不可行的。

示例场景简介

整个示例框架包含了很多场景。最好的学习方法就是进入场景中尝试。我们先作为测试人员来看看这几个场景。

十字准星

这个示例展示了基于注视位置的十字准星或者瞄准器,并探讨了一些必须注意的相关因素。在非VR游戏中,十字准星是否位于视野中心是无关紧要的,但VR开发者则必须要确定十字准星显示位置所代表的深度信息。十字准星的位置如果太近,观察者就会不舒服。如果太远,当准星看起来比场景中位于它下面的物体还远时,又会让玩家产生深度上的错觉。

解决该问题的方法之一,是沿着玩家的视角进行光线投射,并将十字准星定位在视线接触到的第一个物体上。这样就能保证十字准星处在一个合适位置的同时不与场景中的深度信息冲突。你可以在示例中尝试上述方法或一些其它的解决方法,还可以在运行时手动控制十字准星的深度。

这个示例也展示了一些其它概念,例如导弹是如何投射的。如果将十字准星对准导弹,并且该准星与玩家保持固定的距离,就必须决定导弹是沿着从枪口出发的一条轨迹穿过十字准星,还是沿着玩家视觉中心与准星连线的平行线穿过十字准星。后者是非VR游戏的常用做法,这种方法很直观。这个示例可以让你更直接的感受并理解这种区别。

运动

这个示例场景可以体验到第一人称视角的实时移动控制,从而可以更好理解相关设计上的权衡。第一人称视角的移动控制设计需要非常小心,因为这种移动很容易造成不适感。

这个场景可以调整的变量有:

移动速度

旋转速度

玩家朝向是否由视觉方向控制

旋转的步长(持续旋转或者使用固定步骤指定步长的旋转)

当执行“每一步”旋转时的动画速度(非瞬间完成)

瞬移

瞬移是VR中常用的移动方式,因为这样可以避免第一人称视角控制运动引起的不适感。这个示例场景实现了简单的瞬移机制。

这个示例中展示的一个巧妙设计是玩家在瞬移后视角位置的旋转方式。这种模式中,瞬移后视角的方向是由玩家控制的,这个方向可以在瞬移前就设定好。上面的截图展示的就是这个操作,一个发光的虚拟人物出现在了瞬移的终点,展示了瞬移后玩家的朝向且可以由玩家来控制。在瞬移结束后,玩家面对的方向与之前设定的虚拟人的朝向是一致的。

这看起来很直观,但可能存在玩家需要旋转头部才能看到瞬移终点的情况。这时玩家在瞬移完成后朝向与模型保持一致同时头部旋转呢?还是将最终朝向与旋转头部后的自然前方保持一致呢?

这个示例展示了以上两种方式,至于哪一种更直观则取决于另一些因素。示例可以帮助你很直观的理解这两种模式的区别,并探索出个性化的解决方案。

UI(用户界面)

场景“Pointers” (指示点)和“Pointers – Gaze
Click”(指示点-凝视点击)展示了利用指示点来实现VR中的UI交互。两个场景均展示了基于凝视的交互机制,包含了与物理对象和平面UI的交互。

场景“Pointers” (指示点)和“Pointers – Gaze Click”(指示点-凝视点击)很相似,只是“Pointers – Gaze
Click”(指示点-凝视点击)并不需要手柄或者触摸板。在这个场景中,凝视一个UI元素时会在凝视光标附近产生一个圆形的进度条,进度条会很快填充满(如上图所示)。当环形进度条填充完毕,就会执行相应UI所负责的动作。

其它示例场景

篇幅有限无法一一介绍每个场景,各场景都包含对应的文档,我们可以在VR应用内查看这些文档。其它场景包括:

Keyboard:VR键盘的简单实现。

Mirror:展示了模型头部按照玩家头部动作进行运动,以实现场景中的镜像效果。

Stairs:探索楼梯效果在第一人称视角下体验的舒适度。

Surface Detail:探索不同着色技术所描绘出的不同表面细节,可以更好的理解它们在VR中的效果。

Tracking Volume:展示一些方法,在用户离跟踪边界范围太近时给予提示。

结论

这些示例只能作为理解和探索VR中一些常用设计的出发点。事实上,这些示例只是不断发展的VR交互中最浅显的部分。希望各位开发者能觉得这个出发点对你将来的新设计思路有一定帮助。

Unity新UI系统概述Auto-Layout

Rect Transform拥有的布局系统对于各种类型的布局是足够灵活的,并且它也可以让你自由放置元素。但是,有时候更多结构化的东西是需要的。

自动布局系统提供了在嵌套布局组(如水平组、竖直组或者格子组)中放置元素的方法。它还允许元素根据包含的内容量自动调整大小。例如,一个按钮可以根据文本的内容自动缩放大小。

自动布局系统是一个构造在基本Rect Transform布局系统之上的系统。它可以选择性的对一些或全部元素使用。

理解布局元素

自动布局系统是基 layout elements (布局元素)和 layout controllers
(布局控制器)的。布局元素是一个含有RectTransform组件和其它可选组件的游戏对象。Thelayout element has certain
knowledge about which size it should
have.布局元素不能直接设置自己的大小,但是其它作为布局控制器的组件可以使用它们提供的信息用来为它们计算尺寸。

一个布局元素用下列属性来定义自身:

Minimun width(最小宽度)

Minimum height(最小高度)

Preferred width(首选宽度)

Preferred height(首选高度)

Flexible width(灵活宽度)

Flexible height(灵活高度)

使用布局元素提供信息的布局控制器的例子是 Content Size Fitter 和各种 Layout Group
组件。在布局组中如何按大小来布局元素的基本原则如下:

最开始只分配最小尺寸;

如果有足够的空间,分配首选尺寸;

如果有额外的空间,分配灵活尺寸;

含有RectTransform组件的任何游戏对象都可以作为布局元素使用。默认它们的最小、首选和灵活尺寸都是0。某些组件添加到游戏对象上后会改变这些布局属性值。

Image和Text组件就是两个会提供布局元素属性值的例子。它们会改变首选宽度和高度以匹配精灵或者文本内容。

Layout Element组件

如果你想覆盖最小、首选或者灵活尺寸,你可以通过为游戏对象添加一个Layout Element组件来完成。

Layout Element组件可以让你覆盖一个或多个布局属性值。勾选对应控件,然后指定你需要覆盖的数值。

请参看Layout Element参考文档获取更多的信息。

理解布局控制器

布局控制器一些是用来控制一个或多个布局元素尺寸和位置的组件,它也含有Rect Trasnform组件。一个布局控制器可能控制它的 own layout
element
(自己所在的同一个对象)或者控制 child layout elements

Content Size Fitter(内容尺寸适应器)

Content Size Fitter用于控制自身布局元素的尺寸。查看自动布局系统执行方式的最简单方法就是增加一个Content Size
Fitter组件到含有Text组件的游戏对象上。

如果你将Horizontal Fit或Vertical Fit设置为Preferred Size,Rect
Transform组件就会自动调整它的宽或高以适应文本呢内容。

请参看Content Size Fitter相关参考文档。

Aspect Ratio Fitter(纵横比适应器)

Aspcet Ratio Fitter用于控制自身布局元素的尺寸。

它可以让高度适应宽度,反之亦然,也可以让元素放在父对象的内部或者包裹父对象。Aspcet Ratio Fitter不会考虑最小尺寸和首选尺寸等布局信息。

请参看Aspect Ratio Fitter相关参考文档。

Layout Group(布局组)

Layout Group是用来控制子布局元素的大小和位置的控制器。例如,水平的布局组将它的子对象相邻的放置,而格子布局组将它的子对象放在格子里。

布局组不能控制自己的大小。但可以作为一个布局元素被其它控制器控制或者手动设置。

不管布局组如何分配尺寸,大多数时候它都是试图用每一个子布局元素设置的minimum,preferred和flexible尺寸来分配适当数量的空间。布局组也可以任意嵌套。

请参看Horizontal Layout Group, Vertical Layout Group和Gird LayoutGroup相关的参考文档。

驱动Rect Transform属性

因为自动布局系统中的布局控制器会自动控制那些不能通过观察窗口或者场景窗口同时进行手动编辑的UI元素的尺寸和位置。而且这些被改变的值在下一次布局计算时会将被重新设置。

为了解决这个问题,Rect Transform有一个 driven properties(被驱动属性)
的概念。比如,将HorizontalFit属性设置到Minimum或者Preferred的Content Size Fitter组件会驱动同对象上Rect
Transform组件的宽度。这个宽度值变为只读并且在Rect Transform的顶端会出现一个小的信息框告知一个或多个属性值被content Size
Fitter驱动。

Rect
Transform属性被驱动除了避免手动编辑之外还有其它原因。仅仅是通过改变分辨率或者游戏窗口大小就会引起布局的改变。这反过来会改变布局元素的尺寸和位置,也就会改变被驱动属性的值。但是并不希望仅仅因为改变了游戏窗口的大小就会造成场景被标记为未被保存状态。为了避免这个问题,被驱动属性的值不会和场景一起保存并且他们的改变也不会引起场景数据的改变。

自动布局系统伴随着会使用一些内建的组件,但是它也可能用自定义的方式创建出新的组件来控制布局。这是通过能被自动布局系统的特殊组件接口来实现的。

如果执行了 ILayoutElement 接口,组件就会被自动布局系统当作一个布局元素来对待。

如果执行了 ILayoutGroup 接口,组件就会驱动子对象的RectTransform。

如果执行了 ILayoutSelfController 接口,组件就去驱动自身的Rect Transform。

自动布局系统会按下面的步骤计算并执行布局:

1.
通过调用ILayoutElement组件上的CalculateLayoutInputHorizontal接口计算最小,首选和灵活的宽度。这是按从自下而上的顺序,即子对象比父对象先执行,这样的话,父对象才能拿到子对象的数据以便进行自身的计算;

2.
布局元素的有效宽度被ILayoutController组件上的SetLaytouHorizontal接口计算并设置。这是自上而下进行的,即子对象在父对象之后计算,因为子对象的分配需要根据父对象完整的可用宽度来决定。这一步之后,布局元素的Rect
Transform会拥有新的宽度;

3. 计算高度的最小,首选和灵活值,计算方法和第1步类似,只是接口为CalculateLaytouInputVertical;

4. 计算高度的有效值,计算方法和第2步类似,只是接口为SetLaytouVertical。

触发布局的重建

当组件上的一个属性改变后,会导致当前的布局不再有效,就需要做一个布局的重计算。者会被这个调用触发:

LayoutRebuilder.MarkLayoutForRebuild(transformas RectTransform);

这个重建不会立即发生,而是等到这帧的末尾,也就是渲染之前。不立即执行的理由是因为它会导致在同一帧内地进行多次潜在的布局重建,这会导致性能下降。

RectTransform刷新不及时的解决办法:

http://www.tuicool.com/articles/AnQv2yB

http://www.xuanyusong.com/archives/4234

会触发重建的时机为:

会改变布局的属性设置器(setters);

这些回调函数种:

OnEnable

OnDisable

OnRectRansformDimensionsChange

OnValidate(只有编辑器状态需要,运行时不用)

OnDidApplyAnimationProperties

unity的LayoutGroup分为三种, Horizontal Layout Group(水平布局)Vertical Layout
Group(垂直布局)Grid Layout Group (网格布局)
以前NGUI没有这东西都是自己写工具实现的。为什么我们要布局?我举个例子,布局的时候可以两个cell 和三个cell都居中显示。如下图所示。。

尤其在奖励窗口,因为获取道具的数量是不固定的,所以需要根据不同数量的道具来居中对齐。如下图所示,Padding 就是偏移,因为我的cell 是
95X95,为了居中所以这里设置成 right = -95 top = -95。

Spacing 表示 cell之间的距离。

Child Alignment 表示对齐方式。

Child Force Expand 表示 自适应 宽 和高

在看看cell,注意Layout Group节点下面的所有cell节点都是不能修改Rect
Transform的。因为cell可能下面会放很多图片,这样我们会用个空的gameObject来当父节点。但是这个gameObject的width 和
height 是最小单位,那么Layout Group就不知道怎么来算居中了。如下图所示 这个时候就轮到LayoutElement登场了,
用它来设置一个cell的最大或者最小宽度。

如果运行时实例化后的gameObject 直接放在 Layout Group下面即可。Layout Group会自动计算布局,真的是非常方便。

1
2
3
4
5
6
7
8
9
for(int i =0 ;i <10;i++){

GameObject go = (GameObject)Instantiate(Resources.Load<GameObject>(“item”));

go.transform.parent = transform;

go.transform.localScale = Vector3.one;

}

还有个问题就是隐藏,比如把其中的一个cell setActive = false ,为了不计算隐藏的cell 所以要先把 IngonreLaytout =
true 再 setActivity = false 这一切都可以在代码里面来设置。

代码这样即可。

gameObject.GetComponent().ignoreLayout = true;

gameObject.SetActive(false);

在unity3D4.6中加入了新的Transform 系统”Rect Transform”。新的Rect Transform对应的是以前旧版本的“
Transform 2D”。在这里不过多的介绍Rect Transform,今后我会在之后的文章中讲解到新的Rect Transform。

用过Rect Transform的人都知道,Rect
Transform中rect的Widh/Health并不能Set,于是这样就导致了Widh/Health不能动态的修改。这里我给大家提供一个方法,通过添加Aspect
Ratio Fitter/Content Size Fitter组件,来实现Widh/Health的动态变化。

Aspect Ratio Fitter

Aspect Mode以什么样的模式去调整矩形的纵横比。

None不使用适合的纵横比。

Width Controls Height让Height随着width自动调节

Height Controls Width让width随着Height自动调节

Fit In Parent宽度,高度,位置和锚点被自动调整,以使该矩形拟合父物体的矩形内,同时保持高宽比。该可以是不包括在本RECT父矩形里面的一些空间。

Envelope Parent宽度,高度,位置和锚被自动调整,以使该矩形覆盖父的整个区域,同时保持高宽比。此矩形可能进一步延伸出,使他比父物体正确。

Aspect Ratio宽高比来执行。这是宽度除以身高。

Content Size Fitter

Horizontal Fit用什么样的方法来控制宽度

None不使用任何基于布局元素的宽度。

Minimum使用基于布局元素的最小宽度的宽度。

Preferred使用基于布局元件的优选宽度的宽度。

Vertical Fit用什么样的方法来控制高度

None不使用任何基于布局元素的高度。

Minimum使用基于布局元素的最小高度的高度。

Preferred使用基于布局元件的优选高度的高度。

我个人比较习惯用Content Size
Fitter,只要管理好子物体的元素布局与大小就可以很好的控制Widh/Health。当然,在使用过程中,根据具体情况来选择适合的方法来实现动态的调整Widh/Health。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×