ugui怎么制作背包系统,tmw制作血条

本文目录

tmw制作血条

这篇文章为大家介绍两种血条的制作的方法

第一种就是使用Image搭配遮罩来制作一个血条。

1.新建一个unity工程,然后新建一个场景。

2.Hierarchy面板里新建一个Panel,在右边的inspector里将Color的其调为不透明,颜色调成灰色。

3.在Panel下面新建一个Image,将Rect Transform的Width调为400,Height调为50,为其选上一张适当的的背景图片作为血条的背景,将填充色调为黑灰色。

4.再在Panel下面新建一个Image,命名为fill,同样的将Rect Transform下的Width调为400,Height调为50,为其填充为蓝色,然后将fill设置为的Image的子级,并给Image添加Mask组件。这是左右拖动fill,就是产生如下效果。

5.接下我们为fill添加一个脚本来控制血量。

完成后改变currentHP的值就会发现血条的血量也会跟着变化.

第二种就是使用UGUI自身的的Slider来制作血条,这一种相对第一种来说简单许多。

1.新建一个场景,Hierarchy面板里新建一个Panel,在右边的inspector里将Color的其调为不透明,颜色调成灰色。

2.右击Panel,在UI下选择Slider,然后删除Handle Slide Area,并将Fill Area的Rect Transform的left和Right设置为0,将Fill的width设置为0.将slider的Width调为400,Height调为50。接着将Fill的颜色设置为绿色。设置好如下图所示。

3.下来来到Slider的inspector面板里将Max Value的值设置为100。然后运行工程拖动右侧Value的滑动条就可以控制血量。

ugui怎么制作背包系统,tmw制作血条图1

ug的ui样式编辑器

在NGUI 2.7的示例程序中有Example 7 - Scroll View (Panel),这个滚动视图的例子很好的演示了如何搭建一个可以上下滚动的效果。这个例子中如果选中Center On Items的复选框,那么每次滚动结束都会有一个Grid是正好滚到正中间的。但是这里没有实现让点中的Grid滚到正中间的代码。实现起来很简单,只需要重写UICenterOnChild这个类,在Recenter函数中在计算closest transform,我们只需要把Click 选中的Grid的Transform传到这里,然后在每次Click选中Grid的事件处理中调用这个函数就可以实现这个效果了。

ugui怎么制作背包系统,tmw制作血条图2

unity togglegroup 当前选中的

参考

Unity 3D UGUI Toggle用法教程

Is On :用来表示Toggle当前开关状态,勾选为开;

Graphic :控制Toggle组件开关图片的显示隐藏,默认选取Checkmark,就是那个勾勾图片;

挂上这个脚本,会发现事件中有一个带参数的,还有一个不带参数的:

虽然ListenInFunction是带参数的,但是却要选上面那个绿色不带参数的,刚开始我是懵逼的…………

参照 UGUI中Button和Toggle 添加动态事件 得到了解释:

选下方红色的静态方法,其实UI中会多出一个checkbox,可以指定传入的参数:

当然也可以传入其它类型,比如

参考

Unity UGUI入门组件整理(三)【Toggle组件与Toggle Group组件】

假如初始状态是Toggle3被勾选,当我点击Toggle1勾选时,打印如下:

这样就可以根据名字和选中状态来做逻辑处理了。

是否允许不打开任何开关?如果启用此设置,则按下当前打开的开关会将其关闭,因此没有任何开关处于打开状态。如果禁用此设置,则按下当前打开的开关将不改变该开关的状态。

这个说的有点绕,并且有些博客上还有种错误的说法,就是这个开关能允许Group多选。其实测试一下就知道了,在勾选Allow Switch off时,点击当前选中的Toggle,可以将当前Toggle改成未选择状态,此时整个Group中所有的Toggle都会处于未选择状态。而如果没勾选Allow Switch off,就达不到这个效果,会强迫你必须选一个。

在官方文档中,描述ToggleGroup叫开关组:

UGUI学习笔记(五) ToggleGroup制作选择题单选框

ugui怎么制作背包系统,tmw制作血条图3

ugui layout 性能

一、 UGUI布局系统由 布局元素 (Layout Elements)和 布局控制器 (Layout Controller)组成。

1、布局控制器的基础接口为ILayoutController。

(1)ILayoutController有两个方法,布局系统调用这两个方法的顺序是固定的,首先调用SetLayoutHorizontal,再调用SetLayoutVertical:

A、void SetLayoutHorizontal() :处理水平方向的布局;

B、void SetLayoutVertical() :处理垂直方向的布局。

(2)继承ILayoutController的两个接口:

A、ILayoutSelfController :只控制自己RectTransform的改变;继承ILayoutSelfController的两个类如下:

[1] (内容尺寸适配器) Content Size Fitter  <—— ILayoutSelfController:根据孩子中布局元素的尺寸及自身包含内容的多少控制自身的尺寸;

[2] (纵横比适配器) AspectRatioFitter  <—— ILayoutSelfController:根据自身设置的模式(AspectMode)和比率(Aspect Ratio)以及宽或高调整另一边的大小,不受子元素的影响。

B、ILayoutGroup :控制所有孩子节点的布局变化。这个接口就是我们比较熟悉的接口,平时项目中使用的很多布局组件都继承该接口:

[1] ScrollRect   <—— ILayoutGroup;

[2] GridLayoutGroup   <—— LayoutGroup  <—— ILayoutGroup;

[3] HorizontalLayoutGroup\VerticalLayoutGroup->HorizontalOrVerticalLayoutGroup  <—— LayoutGroup <—— ILayoutGroup

2、所有包含RectTransform组件的GameObject都视为布局元素。

(1)布局元素拥有一些定义自身尺寸的属性:

A、Minimum width:最小宽度;

B、Minimum height:最小高度;

C、Preferred width:如果有充足的空间可以分配的最合适宽度;

D、Preferred height:如果有充足的空间可以分配的最合适高度;

E、Flexible width:灵活宽度,一般是相对于父元素的比例;

F、Flexible height:灵活高度,一般是相对于父元素的比例。

默认情况下,Minimum width、Minimum height、Preferred width、Preferred height均为0,Flexible width、Flexible height都是disabled的。如果想调整这些属性就需要添加继承ILayoutElement接口的组件重写这些值。像我们常用的Text、Image组件都继承了ILayoutElement;同时一些布局控制器自身也继承了ILayoutElement,如:LayoutGroup(包括所有继承LayoutGroup的子类)、ScrollRect;UISystem也创建了一个单独组件LayoutElement继承ILayoutElement,任何一个想重写上述属性的GameObject都可以通过添加LayoutElement组件实现。LayoutElement同时继承了ILayoutIgnorer接口,可以通过设置ignoreLayout决定该GameObject是否被Layout System忽略。

(2)ILayoutElement定义了布局元素用到的属性minWidth、preferredWidth、flexibleWidth、minHeight、preferredHeight、flexibleHeight,

同时定义了两个方法:

void CalculateLayoutInputHorizontal():计算布局元素的minWidth,preferredWidth和flexibleWidth值

void CalculateLayoutInputVertical():计算布局元素的minHeight,preferredHeight和flexibleHeight值

二、布局重建过程

1、首先引起布局重建的元素调用LayoutRebuilder.MarkLayoutForRebuild() ,然后逐层向上递归查找直到找到最上层的布局根节点,这个根节点必须包含继承ILayoutGroup接口、Behaviour类并且isActiveAndEnabled属性为true的组件。然后以这个根节点初始化一个布局重建器LayoutRebuilder,然后将该LayoutRebuilder添加到CanvasUpdateRegistry中m_LayoutRebuildQueue队列中等待处理。调用过程如下:

static void LayoutRebuilder.MarkLayoutForRebuild(RectTransform rect) 

->static void LayoutRebuilder.MarkLayoutRootForRebuild(RectTransform controller) 

->static bool CanvasUpdateRegistry.TryRegisterCanvasElementForLayoutRebuild(ICanvasElement element) 

-> CanvasUpdateRegistry.InternalRegisterCanvasElementForLayoutRebuild(ICanvasElement element) 

-> 加入m_LayoutRebuildQueue队列中。

其中有一个比较特殊的就是ScrollRect,在ScrollRect的OnEnable()方法和SetDirtyCaching()方法中会先调用CanvasUpdateRegistry.RegisterCanvasElementForLayoutRebuild(this),再调用LayoutRebuilder.MarkLayoutForRebuild(rectTransform)。与LayoutRebuilder比较,ScrollRect本身也继承了ICanvasElement接口。在Rebuild()函数中,ScrollRect针对CanvasUpdate.Prelayout(布局执行前)和CanvasUpdate.PostLayout(布局执行后)两个阶段实现了自己的执行逻辑。而LayoutRebuilder的Rebuild()函数只针对CanvasUpdate.Layout阶段实现对应的执行逻辑

2、CanvasUpdateRegistry构造函数中会将PeformUpdate方法加入Canvas.willRenderCanvases事件中,然后在渲染所有的Canvas之前,抛出willRenderCanvases事件从而调用PeformUpdate(),在PeformUpdate函数中执行步骤如下:

(1)首先会删除m_LayoutRebuildQueue中所有无效的元素;

(2)然后根据节点的深度(父节点个数越大越靠前)对m_LayoutRebuildQueue排序;

(3)然后分别以CanvasUpdate.PreLayout(布局前),CanvasUpdate.Layout(布局),CanvasUpdate.PostLayout(布局后)的参数顺序调用每一个ICanvasElement元素的Rebuild方法;

(4)然后调用所有ICanvasElement元素的LayoutComplete()方法。针对该方法只有LayoutRebuilder类中实现:将该LayoutRebuilder从LayoutRebuilder的静态对象池s_Rebuilders中删除;

(5)然后清空m_LayoutRebuildQueue队列;

(6)布局结束后调用ClipperRegistry.instance.Cull()遍历所有裁剪组件(继承IClipper接口的组件,如RectMask2D)的裁剪方法PerformClipping()。 

3、下面看一下ICanvasElement布局重建过程的实现,重建的实现就在LayoutRebuilder的Rebuild方法中,源码如下:

如上所示,整个布局分四个步骤:

(1)对该节点下所有有效(继承Behaviour且isActiveAndEnabled为true)的布局元素(即包含继承ILayoutElement组件的节点)执行CalculateLayoutInputHorizontal()计算水平方向布局尺寸。对孩子的遍历顺序由下往上,因为父节点尺寸计算依赖于子节点的尺寸;虽然针对所有布局元素,但是真正实现CalculateLayoutInputHorizontal()方法的只有LayoutGroup相关的组件。

LayoutGroup实现了一个虚方法CalculateLayoutInputHorizontal(),主要就是收集其子节点下所有没有被标记 ignoreLayout 的物体存到m_RectChildren列表中。LayoutGroup的子类重写该函数时都会先调用这个虚函数,然后再执行自己特有的逻辑。

A、 水平布局组件 HorizontalLayoutGroup <—— HorizontalOrVerticalLayoutGroup <—— LayoutGroup

重写CalculateLayoutInputHorizontal()。如上,首先调用LayoutGroup中CalculateLayoutInputHorizontal()方法,然后调用HorizontalOrVerticalLayoutGroup中的CalcAlongAxis(int axis, bool isVertical)方法,CalcAlongAxis()是一个公用方法,可以根据传入的参数确定计算哪个方向的尺寸,其中axis表示方向(0:horizontal 1:vertical),isVertical判断是否一个Vertical Group。CalcAlongAxis()执行过程如下:

① 首先遍历所有孩子节点调用GetChildSizes()方法获取对应方向上的尺寸(min、preferred、flexible);

② 然后根据所有子节点的尺寸计算当前节点对应方向上的尺寸totalMin、totalPreferred、totalFlexible;

③ 调用SetLayoutInputForAxis()方法将第二步计算的值设置对应的向量m_TotalMinSize、m_TotalPreferredSize、m_TotalFlexibleSize;

B、垂直布局组件VerticalLayoutGroup 重写方法如下,实现参考HorizontalOrVerticalLayoutGroup

(2)对该节点下所有布局控制器(即包含继承ILayoutController组件的节点)执行SetLayoutHorizontal()设置水平布局。对孩子的遍历顺序自上而下,因为孩子节点实际的布局依赖于父节点的布局;

A、HorizontalLayoutGroup和VerticalLayoutGroup中的SetLayoutHorizontal()会直接调用HorizontalOrVerticalLayoutGroup.SetChildrenAlongAxis()方法根据布局方向和布局组件类型设置其下子布局元素的位置和尺寸。

B、GridLayoutGroup也重写了SetLayoutHorizontal()方法,直接调用SetCellsAlongAxis(0),针对水平布局实现如图2-4所示,只设置每个子元素的尺寸,而不会改变子元素的位置。

(3)对该节点下所有布局元素(即包含继承ILayoutElement组件的节点)执行CalculateLayoutInputHorizontal()计算垂直方向布局尺寸;对孩子的遍历顺序由下往上;

(4)对该节点下所有布局控制器(即包含继承ILayoutController组件的节点)执行SetLayoutVertical()设置垂直布局。对孩子的遍历顺序自上而下;

从上面的执行顺序还可以看出,Layout System先搞定水平方向的布局然后才去设置垂直方向的布局。

三、布局重建触发因素

1、 以下函数,都会直接或间接的调用LayoutBuilder.MarkLayoutForRebuild()触发布局重建:

(1)OnEnable() :所有继承ILayoutController或ILayoutElement组件(AspectRatioFitter除外)的OnEnable()方法都会都会间接调用LayoutBuilder.MarkLayoutForRebuild();

A、Graphic :OnEnable() -> SetAllDirty() -> ( m_SkipLayoutUpdate变量为false时才会调用 )LayoutBuilder.MarkLayoutForRebuild();

B、LayoutGroup\ContentSizeFitter\LayoutElement\ScrollRect :OnEnable() -> SetDirty() -> LayoutBuilder.MarkLayoutForRebuild()。

(2)OnDisable() :所有继承ILayoutController或ILayoutElement组件的OnDisable()方法都会调用LayoutBuilder.MarkLayoutForRebuild()

(3)OnRectTransformDimensionsChange(): RectTransform尺寸变化时调用。继承自UIBehaviour的ContentSizeFitter、LayoutGroup、ScrollRect、Graphic都重写了该方法,具体调用如下:

A、ContentSizeFitter :OnRectTransformDimensionsChange() ->SetDirty() -> (IsActive()为true才会调用)LayoutRebuilder.MarkLayoutForRebuild();

B、LayoutGroup :OnRectTransformDimensionsChange() ->(isRootLayoutGroup为true时才会调用)SetDirty() ->(IsActive()为true时才会调用)LayoutRebuilder.MarkLayoutForRebuild();

C、ScrollRect :OnRectTransformDimensionsChange() -> SetDirty() ->( IsActive()为true时才会调用 )LayoutRebuilder.MarkLayoutForRebuild();

D、Graphic :OnRectTransformDimensionsChange() ->( gameObject.activeInHierarchy为true时才会调用 )SetLayoutDirty() ->(IsActive()为true时才会调用)LayoutRebuilder.MarkLayoutForRebuild();

(4)OnDidApplyAnimationProperties(): 动画导致属性( 重写OnDidApplyAnimationProperties()方法的类自身所特有的属性 )改变时调用。继承UIBehaviour的Graphic、LayoutGroup、LayoutElement都重写了该方法,具体调用如下:

A、Graphic :OnDidApplyAnimationProperties() -> SetAllDirty() -> ( m_SkipLayoutUpdate变量为false时才会调用 )LayoutBuilder.MarkLayoutForRebuild()。Graphic本身是个抽象类,不能当作组件直接添加,而继承自Graphic的Image\Text( ——> MaskableGraphic  ——> Graphic)组件的一些特有属性,如图3-1红框内标记,当动画改变Text的这些属性时会调用OnDidApplyAnimationProperties()函数。如图3-2红框内标记,当动画改变Image的这些属性时会调用OnDidApplyAnimationProperties()函数。

B、LayoutGroup :OnDidApplyAnimationProperties() -> SetDirty() -> ( IsActive()为true时才会调用 )LayoutBuilder.MarkLayoutForRebuild()

如图3-3、3-4、3-5分别是VerticalLayoutGroup、HorizontalLayoutGroup,当动画改变VerticalLayoutGroup的这些属性时会调用OnDidApplyAnimationProperties()函数。

C、LayoutElement :OnDidApplyAnimationProperties() -> SetDirty() -> ( IsActive()为true时才会调用 )LayoutBuilder.MarkLayoutForRebuild()

如图3-6所示,当动画改变LayoutElement的这些属性时会调用OnDidApplyAnimationProperties()函数。

(5)OnBeforeTransformParentChanged() :父节点transform属性变化前调用。继承自UIBehaviour的Graphic和LayoutElement类都重写了该方法:

A、Graphic :OnBeforeTransformParentChanged() -> SetAllDirty() -> LayoutBuilder.MarkLayoutForRebuild()

B、LayoutElement :OnBeforeTransformParentChanged() -> SetDirty() -> LayoutBuilder.MarkLayoutForRebuild()

2、 某些组件特有属性变化或函数调用:

(1)RectTransform 中导致布局变化的属性:Width、Height、Scale、以及锚点变化;

(2)Text 中导致布局变化的属性:text、alignment、fontSize、horizontalOverflow、verticalOverflow、lineSpacing、fontStyle、resizeTextForBestFit、resizeTextMinSize、supportRichText、resizeTextMaxSize、font;方法:FontTextureChanged()。

(3)Image 中导致布局变化的属性:sprite、overrideSprite;方法:SetNativeSize()、OnCanvasHierarchyChanged()。其中OnCanvasHierarchyChanged()只有在canvas.referencePixelsPerUnit变化且Image类型为Sliced或Tiled时才会调用SetLayoutDirty()

(4)LayoutGroup 中导致布局变化的属性:padding、childAlignment;方法:OnTransformChildrenChanged()

(5)GridLayoutGroup 中导致布局变化的属性:startCorner、startAxis、cellSize、spacing、constraint、constraintCount

(6)HorizontalOrVerticalLayoutGroup 中导致布局变化的属性:spacing、childForceExpandWidth、childForceExpandHeight、childControlWidth、childControlHeight、childScaleWidth、childScaleHeight

(7)ContentSizeFitter 中导致布局变化的属性:horizontalFit、verticalFit

(8)LayoutElement 中导致布局变化的属性:ignoreLayout、minWidth、minHeight、preferredWidth、preferredHeight、flexibleWidth、flexibleHeight、layoutPriority

(9)ScrollRect 中导致布局变化的属性:verticalScrollbar、horizontalScrollbar、horizontalScrollbarVisibility、verticalScrollbarVisibility、viewport

四、布局重建分析工具

1、第三节我们总结了一些可能导致布局重建的原因,游戏中尽量避免执行这些操作以减少布局重建,同时尽可能少的使用Layout相关组件以减少CPU时间的占用。通过第二节对重建过程的分析,我们知道每个引起布局重建的元素的元素都会先加入CanvasUpdateRegistry中m_LayoutRebuildQueue队列中,所以我们可以通过反射的方式来获取游戏中引起布局重建的元素(引用

),脚本如下:

public class CheckRebuildElement:MonoBehaviour

{

       IList m_LayoutRebuildQueue;

        privatevoid Awake()

        {

           System.Type type = typeof(CanvasUpdateRegistry);

           FieldInfo field = type.GetField("m_LayoutRebuildQueue",BindingFlags.NonPublic | BindingFlags.Instance);

           m_LayoutRebuildQueue = (IList)field.GetValue(CanvasUpdateRegistry.instance);

        }

        privatevoid Update()

        {

            for(int j = 0; j ugui怎么制作背包系统,tmw制作血条图4

以上就是关于ugui怎么制作背包系统,tmw制作血条的全部内容,以及ugui怎么制作背包系统的相关内容,希望能够帮到您。

版权声明:本文来自用户投稿,不代表【蒲公英】立场,本平台所发表的文章、图片属于原权利人所有,因客观原因,或会存在不当使用的情况,非恶意侵犯原权利人相关权益,敬请相关权利人谅解并与我们联系(邮箱:350149276@qq.com)我们将及时处理,共同维护良好的网络创作环境。

(0)
上一篇 2023年10月07日 09:17
下一篇 2023年10月07日 09:27

相关推荐

  • 京豆可以赠送给别人,京豆和余额哪个好

    本文目录1.京豆和余额哪个好2.京东京豆能不能送人3.京东里的京豆可以赠送别人吗4.京东京豆怎么赠送京豆和余额哪个好e卡好。e卡和京豆是中国电商平台京东提供的两种虚拟货币,e卡是一种电子礼品卡,可以用于购买京东平台上的商品,也可以作为礼品赠送给他人。京豆是一种积分,可以用于抵扣商…

    2023-10-07
  • 尼康d7000怎么测光锁定,尼康d7000fn按键是什么

    本文目录1.尼康d7000fn按键是什么2.尼康相机wifi怎么连接手机3.尼康d7000怎么恢复出厂设置方法4.尼康d7000怎么恢复出厂设置方法尼康d7000fn按键是什么设定为评价测光时,半按快门键会锁定曝光设置;在局部测光、点测光、中央重点测光时半按快门不会锁定曝光。尼康…

    2023-10-07
  • 为什么腊月不提亲,为什么腊月不订婚正月不结婚

    本文目录1.为什么腊月不订婚正月不结婚呢2.六腊月不结亲的由来 六腊月不提媒是指什么3.六腊月不提亲是什么意思是阳历还是阴历4.为什么腊月不能提亲为什么腊月不订婚正月不结婚呢一般到了腊月这个月,结婚的人是非常的多的,基本上每天我们都能看到婚车在马路上来回的行驶着。不过不知道大家有…

    2023-10-07
  • 互免拍摄是什么,摄影师说互勉是什么意思

    本文目录1.互免约拍是啥意思2.摄影说的互勉是什么意思3.互免约拍是什么意思4.摄影师跟你说互勉是什么意思互免约拍是啥意思互免约拍指的是摄影师与模特相互免收费用。摄影师为模特免费拍摄,模特为摄影师当免费模特。摄影师与模特可以互相提高自己的能力,找对方一起创作作品,相互不收取费用的…

    2023-10-07
  • 什么时候贴春联,应该什么时候贴春联

    本文目录1.春节贴对联什么时候最合适2.过春节一般什么时候贴对联3.什么时侯贴春联4.春联什么时候贴春节贴对联什么时候最合适春节贴对联腊月二十九和三十最合适。贴春联最好是除夕早上6点到中午12点之间。民间有一种神话的传说:春联即为天上的神仙,当春联撕破后,就会升上天庭,去向玉皇大…

    2023-10-07
  • 压缩方式有什么区别,压缩包的格式有什么区别

    本文目录1.压缩包的格式有什么区别2.压缩文件的压缩方式怎么选3.压缩文件这三种格式有什么区别呢4.压缩文件格式rar和zip有什么区别图片哪个清晰压缩包的格式有什么区别压缩包的格式不同,但是在操作和浏览方式上没有任何区别,仅在效率和处理能力上存在差异。不同格式之间的差异:1.Z…

    2023-10-07
  • 大运河修建于什么朝代,京杭大运河始建于什么时候什么朝代

    本文目录1.京杭大运河哪个朝代修建的2.京杭大运河始建于哪个朝代3.大运河是哪个朝代的4.京杭大运河始建于 京杭大运河建于哪个朝代京杭大运河哪个朝代修建的京杭大运河是春秋时期修建的,京杭大运河是我国乃至全世界最常、规模最大的运河,也是最古老的运河之一。它最开始是春秋吴国为了讨伐齐…

    2023-10-07
  • 尼康d90如何连拍,尼康d90出现err黑屏不能照相

    本文目录1.尼康d90出现err黑屏不能照相2.尼康单反机 怎么调连拍模式3.尼康d90录像功能怎么打开4.尼康D90如何连拍尼康d90出现err黑屏不能照相尼康D90单反相机实现连拍的镜头步骤是:1.给尼康D90单反相机安装充过电的电池。2.给尼康D90单反相机安装高速SD存储…

    2023-10-07
  • 垃圾分类困惑有哪些,社区垃圾分类存在哪些问题

    本文目录1.社区垃圾分类存在哪些问题2.农村垃圾分类处理面临的主要问题有哪些方面3.垃圾分类的规则有哪些4.垃圾分类会遇到哪些实际问题呢社区垃圾分类存在哪些问题社区垃圾分类虽可以有效地解决环境污染等问题,但也可能存在以下问题:1.居民知晓率不高,居民理解、掌握的程度不同,不同垃圾…

    2023-10-07
  • 佳能单反如何拍风景,佳能600d单反相机拍的照片焦点清晰周围模糊怎样设置才能拍出全景清晰地...

    本文目录1.佳能600d单反相机拍的照片焦点清晰周围模糊2.佳能单反使用教程图解3.佳能单反必备3个镜头4.佳能5d2风景拍摄参数设置佳能600d单反相机拍的照片焦点清晰周围模糊1.是光圈过大造成的虚化效果,降低光圈数值,一般把光圈调节成F8以上,景深影响就会减小,十几的F值拍出…

    2023-10-07