妄想的咸鱼吧 关注:151贴子:2,416
组件事件和函数
根据组件类型的不同,您可以基于它们在事件图表中添加事件 和/或 函数。比如,另一个actor(比如一个Pawn)穿过 Box Component时,该Box Component可以有一个Overlap事件。以这种方式创建的任何事件或函数都是针对那个特定函数的,不必测试来确认它所涉及的组件。
创组件事件非常简单,如下所示:
创建一个可以为其创建事件的组件。在这个示例中,我们使用一个BoxComponent(盒体组件)。

为您的组件提供一个名称 - 这会为其创建一个变量。

在 Variables(变量) 选卡中,选择该新变量。

在 图表 选卡中,右击弹出关联菜单。如果该组件有任何相关联的事件或函数,都会在顶部列出这些事件或函数。

在这个示例中,我们添加了一个 Overlap事件,每当有actor穿过这个Box Component体积时都会调用该事件。
注意:不是所有的组件都有相关联的事件。比如,一个Point Light Component(点光源组件)仅具有函数。
构造脚本
当创建 类蓝图 时, Construction Script(构造脚本) 在 Components(组件) 列表 之后运行。构造脚本包含一个节点图表,执行该图表使得该 类蓝图 实例执行初始化操作。 这个功能非常强大,因为像在世界中执行追踪、设置网格物体及材质等这样的动作可以用于 实现情境关联的设置。比如,一个光源的 蓝图 可以决定它所放置到的地面的类型, 且可以从一组网格物体中选择要使用的正确的网格物体;或者一个篱笆 蓝图 ,它可以在各个方向上 进行追踪,来决定篱笆需要有多长才能跨越那个距离。
注意:仅类蓝图包含 Construction Scripts(构造脚本) 。关卡蓝图没有构造脚本。
Construction Script(构造脚本) 图表的执行入口点是一直存在的 ConstructionScript 节点。

蓝图调试
蓝图调试是一种非常强大的功能,允许您在Play In Editor(在编辑器中运行)或Simulate In Editor(在编辑器中模拟)模式下使用断点来中止游戏执行过程,并单步调试任何蓝图图表或关卡蓝图。
调试控件允许您在Play In Editor和Simulate In Editor模式下控制游戏的执行过程。当游戏运行时,会在蓝图编辑器中启用这些控件。根据所调试的 蓝图 及当前调试状态的不同, 会在工具条 上出现不同的调试按钮。一些控件仅当遇到相关 断点 时才会激活。

当激活 Simulate in Editor 或 Play in Editor模式时, Debug(调试) 选卡和 Blueprint Debugger(蓝图调试器) 都将会显示情境关联的调试按钮。其中 Debug(调试) 选卡可以从 蓝图编辑器 中的 Graph(图表) 模式下打开。

断点
当从编辑器中运行游戏时,Breakpoints(断点) 可以在任何点处中止游戏的执行过程。属于一个蓝图或关卡蓝图的所有图表的所有断点都会显示在 Debug(调试) 选卡中。该列表中的断点名称都有超链接,您可以点击它们,并直接跳转到 Graph(图表) 选卡中和那个断点相关的节点处。
您可以在要执行的图表中任何节点上设置断点,比如 Function Calls(函数调用) 和 Flow Control(流程控制) 操作,只需通过右击节点并选择 Add breakpoint(添加断点) 即可设置断点。当已经在一个节点上设置了断点时,会在该节点的左上角上显示一个图形。

通过右击断点并选择 Disable breakpoint(禁用断点) 或者点击 Debug(调试) 菜单中断点旁边的图标将其关闭,可以禁用断点。这个处理也可以通过右击 Debug(调试) 选卡中的断点并选择 Disable breakpoint(禁用断点) 来完成。
这样做时断点会留在原处,但是当执行该节点时它不会使游戏停止。已禁用的断点仅显示为一个断点轮廓。


IP属地:安徽31楼2017-03-18 16:16
回复
    调试选卡和蓝图调试器
    Debug(调试) 选卡显示了设计师指定的重要信息,信息以断点、查看值及属于已经执行过的蓝图的所有节点的堆栈追踪的形式显示。当使用断点时,这个窗口也显示了用于控制游戏执行的控件。
    变量值查看器
    Watch values(查看值) 允许您在执行过程中快速并轻松地查看变量的值。当调试遇到一个断点后,所有的选中Actor及关卡蓝图的查看值都会显示在调试窗口中,并且随着您单步调试整个图表,这些查看值会随之更新。

    执行追踪
    Execution Trace(执行追踪) 栈显示了所执行的节点的列表,最近执行的节点显示在顶部。

    相当于vs中的调用栈,这个列表随着您单步调试整个图表而进行更新。
    事件调度器
    通过向 Event Dispatcher(事件调度器) 绑定一个或多个事件,您可以在调用该事件调度器后触发所有事件。这些事件可以在类蓝图中进行绑定,但 事件调度器也允许在关卡蓝图激活这些事件。
    创建事件调度器
    要想创建一个新的事件调度器:
    点击 我的蓝图 选卡顶部的 New Event Dispatcher按钮。
    在 我的蓝图 选卡中的列表尾部出现的名称文本域中,输入该事件调度器的名称。

    设置属性
    通过在 我的蓝图 选卡内选中该事件调度器,您可以在 详细信息 面板中编辑其属性。您可以为您的事件调度器设置工具提示信息和类目,且可以添加输入。
    给您的事件调度器添加输入,允许您向绑定到您的事件调度器的每个事件发送变量。这使得数据不仅可以在您的类蓝图中流动,且可以在您的类蓝图和关卡蓝图 之间流动。
    给您的事件调度器添加输入的过程和给函数、自定义事件及宏添加输入及输出的流程类似。如果您想使用和另一个事件相同的输入,那么您可以使用 Copy Signature from(复制签名) 下拉菜单来指定该事件。 要想给该事件调度器添加您自己的输入:
    点击 详细信息 面板的 Inputs(输入) 部分的 New(新建) 按钮。

    命名该新输入并使用下拉菜单设置其类型

    使用事件调度器
    一旦您创建了事件调度器后,您可以添加事件节点、绑定节点及解除绑定连接到其上面的节点。尽管您可以在 我的蓝图 选卡中双击事件调度器选项来打开 事件调度器的图表,但是该图表是锁定的,您不能直接修改该事件调度器。绑定、解除绑定及分配方法都允许您向事件调度器的事件列表添加事件, 但调用方法将激活事件图表中存储的所有事件。
    创建调度器事件
    通过使用Event Dispatcher(事件调度器)菜单上的 Event(事件) 选项创建一个具有正确签名的自定义事件, 使得该事件可以绑定到该事件调度器上。 尽管这个事件节点的看上去和没有连接到 Bind 节点的自定义事件节点类似, 但是当执行 Call [事件调度器名称] 节点时将永远不会触发该事件。
    在类蓝图中进行创建

    在 My Blueprint(我的蓝图) 选卡下,从 Event Dispatcher(事件调度器)名称处开始拖拽鼠标并将其放置到您正处理的图表中。
    在出现的菜单中选择 Event(事件) 。

    在关卡蓝图中进行创建
    在关卡蓝图中,可以创建一种特殊类型的Event Dispatcher(事件调度器)事件,此时事件会自动绑定到事件调度器上。 创建这些事件的步骤和创建默认事件(比如 OnClicked 或 OnOverlap 事件) 一样。 关卡蓝图文档中提供了关于这个过程的 详细介绍。
    绑定及解除绑定事件

    如果没有事件绑定到事件调度器,那么调用该事件调度器将不会产生任何效果。鉴于每个事件调度器都有一个和其相关的事件列表。向该列表中添加一个事件的方法是使用 Bind Event(绑定事件) 节点,从该列表中删除事件的方式是使用 Unbind Event(解除绑定事件) 节点。另外,通过使用 Unbind All Events(接触绑定所有事件) ,还可以解除当前绑定到事件调度器上的所有事件
    尽管 绑定事件 节点可以执行多次,但每个事件仅能绑定一次。同时, 类蓝图 和 关卡蓝图 中的事件都添加到同一个事件列表中,所以 Unbind All Events(解除绑定所有事件) 节点将会取消绑定 类蓝图 和 关卡蓝图 中的所有事件。
    在 类蓝图 中执行 Unbind All Events(取消绑定所有事件) 节点,将针对该类的所有实例,取消绑定 类蓝图 和 关卡蓝图 中的事件。
    在 关卡蓝图 中执行 Unbind All Events(取消绑定所有事件) 节点,将仅针对 Target 端提供的内容,取消绑定 类蓝图 和 关卡蓝图 中的事件。
    在类蓝图中进行创建


    IP属地:安徽32楼2017-03-18 16:16
    回复
      在类蓝图中进行创建
      两种方法:
      在出现的菜单中选择 Bind(绑定) 。

      在图表中 右击,在出现的关联菜单中展开 Event Dispatcher(事件调度器)

      在关卡蓝图中进行创建
      添加到关卡中您想为其调用事件调度器的Actor的引用。
      从该引用节点的输出引脚开始拖拽鼠标,然后释放鼠标来显示关联菜单

      调用事件调度器

      使用 Call 节点调用一个Event Dispatcher(事件调度器),将会触发绑定到该事件调度器的所有事件。对于每个事件调度器,您可以应用多个 Call 节点,且您既可以在 类蓝图 中调用事件调度器也可以在 关卡蓝图 中进行调用。
      在蓝图调用
      两种方法:
      在 My Blueprint(我的蓝图) 选卡下,从 Event Dispatcher(事件调度器)名称处开始拖拽鼠标并将其放置到您正处理的图表中在出现的菜单中选择 Call(调用)

      右击图表,在出现的关联菜单中展开 Event Dispatcher(事件调度器)

      在关卡蓝图中进行调用
      添加到关卡中您想为其调用事件调度器的Actor的引用。
      从该引用节点的输出引脚开始拖拽鼠标,然后释放鼠标来显示关联菜单。

      蓝图交互的用法
      直接交互
      引用了一个蓝图的实例,这样就可以直接通过这个实例来调用函数等。

      使用场合:
      当你关卡中有一个Actor,而想跟另外一个Actor通信的时候。
      事件调度器

      使用场合:
      角色的蓝图想要跟关卡蓝图通信时。
      当一个生成的Actor做了某些事情时,你想要触发事件时。


      IP属地:安徽33楼2017-03-18 16:16
      回复
        蓝图接口

        使用场合:
        在蓝图中有一个功能会产生不同的行为时。
        类型转换

        使用场合:
        你有一个角色需要跟关卡中的Actor进行交互,这时需要改变角色的类型时。
        你想缎带HUD或者UI控件传递变量时。
        你有多个蓝图,这些蓝图有继承关系,你想要把它转换成某个子蓝图。
        你有一个蓝图,这个蓝图依赖于另外一个蓝图的变量、事件、函数。
        你想获取多个蓝图的同一个基类,并且要同时修改它们。
        作者: 风恋残雪
        出处: http://www.cnblogs.com/ghl_carmack
        关于作者:专注游戏引擎,关注VR,对操作系统、编译原理有深厚兴趣!
        本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接,否则保留追究法律责任的权利。


        IP属地:安徽34楼2017-03-18 16:17
        回复
          虚幻4蓝图快速入门(四)


          IP属地:安徽35楼2017-03-18 16:17
          回复
            蓝图跟C++交互
            概述
            蓝图可以继承C++类,从而使得程序员可以在代码中创建新的游戏性类,而关卡设计人员可以使用蓝图来继承该类并对其进行修改。 有很多种修饰符可以改变C++类和蓝图系统间交互方式,其中某些修饰符会在本示例中突出介绍。
            可以通过查看以下内容来快速了解:
            虚幻引擎快速入门视频教程第五章,见引用[1]
            官方文档
            类设置
            在类设置的第一部分中,使用C++类向导创建一个名称为LightSwitchBoth 的类。
            LightSwitchBoth类中的大部分代码设置都和 仅使用C++的LightSwitch示例 类似。尽管您可以让一个蓝图继承LightSwitchCodeOnly类,但蓝图图表并不能访问该类中创建的组件、属性及函数。该示例将使用 UPROPERTY() 和 UFUNCTION() 修饰符,这两个修饰符使得LightSwitchBoth作为继承它的蓝图的模板。
            这个头文件是从 仅使用C++的LightSwitch示例 改编而来,添加了以下功能:
            PointLightComponent和SphereComponent是BlueprintReadOnly(仅蓝图可读的),并且将显示在 我的蓝图 选卡中的 Switch Components(切换组件) 类目中。
            OnOverlap现在是一个BlueprintNativeEvent,将会显示在 我的蓝图 选卡中的 Switch Functions(切换函数) 类目中。
            DesiredBrightness是BlueprintReadWrite(蓝图可读写的),将显示在 我的蓝图 选卡中的 Switch Properties(切换属性) 类目中。
            DesiredBrightness现在是EditAnywhere(随处可编辑的),而不是VisibleAnywhere(随处可见的)。

            在LightSwitchBoth的源文件中,构造器仍然是一样的。但是,需要对 OnOverlap 函数做一点修改。这个函数现在是一个BlueprintNativeEvent。这意味着 在继承这个类的蓝图中,可以放置一个覆盖 OnOverlap 的事件,当正常调用该函数时会执行此事件。如果该事件不存在,那么则是执行那个函数的 C++实现。要想使这个设置正常工作,该C++函数需要重命名为 OnOverlap_Implementation 。稍后在本示例中将介绍这个蓝图设置。对 OnOverlap 函数 进行了修改后,LightSwitchBoth 的源文件如下所示:

            当创建类时,新的 UCLASS() 、UFUNCTION() 或 UPROPERTY() 宏意味着该代码必须在Visual Studio 或Xcode中进行编译,然后使用虚幻编辑器重新加载它们。 关闭虚幻编辑器,在Visual Studio 或Xcode中编译该项目,然后打开编辑器并重新加载该项目,以确保正确地重新加载该游戏模块。
            当重新打开虚幻编辑器并重新打开您的项目后,便可以创建一个新的类蓝图了。 在本示例中,选择LightSwitchBoth作为该蓝图的父类,蓝图名称为 LightSwitchBoth_BP 。

            在 C++代码中添加的PointLightComponent和SphereComponent 也会显示在 Blueprint Editor(蓝图编辑器) 的 组件模式中的 Components(组件) 选卡内。 它们的图标是深蓝色,表示它们是从父类LightSwitchBoth类继承而来的原生组件。而刚刚添加到 LightSwitchBoth_BP 蓝图中的新组件的图标 是浅蓝色的

            在 Graph Mode(图标模式) 中, My Blueprint(我的蓝图) 选卡显示了在C++中添加到LightSwitchBoth类中的 PointLightComponent 和SphereComponent 。这是因为 BlueprintReadOnly 修饰符存在的缘故。 通过在 我的蓝图 选卡中点击并拖拽这些组件的名称到图表中,可以将这些组件的节点添加到图表中。然后,您可以把这些节点连接到改变像可见性 或光源颜色这样属性的节点上。DesiredBrightness 属性也会出现在 我的蓝图 选卡中。因为它是一个属性,而不是一个组件,所以可以使用 BlueprintReadWrite 修饰符。这意味着在蓝图图表中可以创建节点来获取及设置 DesiredBrightness 的值。
            有两个图表用于设置 LightSwitchBoth_BP 类的行为。第一个是构造脚本图表,它包含了一个专用的 Construction Script(构建脚本)事件。如果没有该 Construction Script 设置,那么新的 LightSwitchBoth_BP Actor 将仅使用LightSwitchBoth的构造函数。然而,当Actor在关卡中移动时,及当 Desired Brightness 发生改变时,都会执行 Construction Script 。使用 Construction Script 意味着,可以轻松地改变暴露给蓝图的Actor属性, 并且可以快速地看到这些修改的效果。
            在 LightSwitchBoth_BP 类中, Construction Script 事件连接到了 Set Brightness 节点上,以便当在关卡中添加或移动Actor时或者 Desired Brightness 发生改变时,将 Point Light 1 (PointLightComponent) 的亮度设置为 Desired Brightness 的值。
            在 LightSwitchBoth_BP 类中, Construction Script 事件连接到了 Set Brightness 节点上,以便当在关卡中添加或移动Actor时或者 Desired Brightness 发生改变时,将 Point Light 1 (PointLightComponent) 的亮度设置为 Desired Brightness 的值。

            LightSwitch_BPOnly 类中设置的另一个图表是 事件图表 。EventGraph的执行是由事件触发的。在这个示例中, 任何时候当调用C++函数 OnOverlap 时, OnOverlap 就会执行。在LightSwitchBoth的源文件中,设置了代理,以便当一个Actor进入或离开SphereComponent时会执行 OnOverlap 。

            在变量的设置中, DesiredBrightness 变量设置为 EditAnywhere (随处可编辑) ,所以在 蓝图编辑器 的默认模式中它是可见的,并且可以进行编辑。 这意味着对于类的每个实例,这个变量是可以变化的,所以每个Actor可以有其自己的 DesiredBrightness 。因为 DesiredBrightness 也是 BlueprintReadWrite(蓝图可读写) 的,且 Construction Script 中使用了它,所以更新它还会导致再次执行 Construction Script 。

            其他Class Blueprints(类蓝图)可以继承由蓝图创建的类,通过以下两种方式实现:使用 Class Viewer(类别查看器) 中的类附近的下拉列表按钮来创建一个新蓝图, 或者通过右击该蓝图并选择 Create New Blueprint Based on This(基于此蓝图创建一个新蓝图) 。


            IP属地:安徽36楼2017-03-18 16:17
            回复
              蓝图函数库
              有时候有一些帮助函数,我们需要在蓝图中使用,这时候我们可以创建一个蓝图函数库。它是一些静态函数的集合。
              创建蓝图库跟使用UFUNCITON()暴露一些函数给蓝图很相似。只需要继承UBlueprintFunctionLibrary即可。它们也应该包含静态函数。

              下面是StartSession的实现

              编译后,就可以在蓝图内里面调用这些方法了。
              属性修饰符
              此处只列举了一些常用的属性,具体参照官方文档
              AdvancedDisplay
              AssetRegistrySearchable
              BlueprintAssignable仅能用于Multicast代理。应显示该属性,以供在蓝图中分配。
              BlueprintCallable仅能用于Multicast代理。应显示该属性,以在蓝图代码中调用。
              BlueprintReadOnly 只读
              BlueprintReadWrite 读写
              Category定义属性的分类

              Config
              Const
              DuplicateTransient
              EditAnywhere表示该属性可从编辑器内的属性窗口编辑。
              EditDefaultsOnly表示该属性可通过属性窗口来编辑,但仅能对原型编辑。
              EditFixedSize
              EditInline
              EditInstanceOnly

              函数修饰符
              函数声明
              UFUNCTION([specifier, specifier, ...], [meta(key=value, key=value, ...)])
              ReturnType FunctionName([Parameter, Parameter, ...])
              函数修饰符
              在声明函数时,声明上可添加修饰符以控制引擎和编辑器的不同方面的属性表现。
              BlueprintAuthorityOnly
              BlueprintCallable 该函数可在蓝图或关卡蓝图图表内执行。
              BlueprintCosmetic 此函数为修饰函数而且无法运行在专属服务器上
              BlueprintImplementableEvent此函数可以在蓝图或关卡蓝图图表内进行重载。
              BlueprintNativeEvent 此函数将由蓝图进行重载,但同时也包含native类的执行。提供一个名称为[FunctionName]_Implementation的函数本体而非[FunctionName];自动生成的代码将包含转换程序,此程序在需要时会调用实施方式。
              BlueprintPure 此函数不会以任何方式影响其从属对象,并且可在蓝图或关卡蓝图图表中执行。
              Category 当在蓝图编辑工具中显示时,定义函数的分类。

              Client此函数仅在该函数从属对象所从属的客户端上执行。提供一个名称为[FunctionName]_Implementation的函数主体,而不是[FunctionName]; 自动生成的代码将包含一个转换程序来在需要时调用实现方法。
              CustomThunk UnrealHeaderTool(虚幻头文件工具)的代码生成器将不会为此函数生成execFoo转换程序; 可由用户来提供
              Exec此函数可从游戏中的控制台中执行。Exec命令仅在特定类中声明时才产生作用。
              NetMulticast无论Actor的NetOwner为何值,此函数都会在服务器上被本地执行且将被复制到所有的客户端
              Reliable此函数在网络间进行复制,并会忽略带宽或网络错误而被确保送达。仅在与客户端或服务器共同使用时可用
              Server此函数仅在服务器上执行。提供一个名称为[FunctionName]_Implementation的函数主体,而不是[FunctionName]; 自动生成的代码将包含一个转换程序来在需要时调用实现方法。
              Unreliable此函数在网络间复制,但可能会由于带宽限制或网络错误而传送失败。仅在与客户端或服务器一起使用时有效。
              类修饰符


              IP属地:安徽37楼2017-03-18 16:18
              回复
                在声明类时,声明上可添加修饰符以控制引擎和编辑器的不同方面的类表现。
                有太多修饰符,此处仅列举一些常用的,其它请参考官方文档。
                Blueprintable指定该类为创建蓝图的可接受基类。除非被继承,否则默认值为NotBlueprintable。它由子类继承。
                BlueprintType此类可作为蓝图中的一种变量类型使用
                Abstract Abstract 类修饰符将类声明为"抽象基类",这样会阻止用户在虚幻编辑器中向这个世界中添加这个类的Actor,或者在游戏过程中创建这个类的实例。
                Deprecated该类已被废弃,并且该类的对象在序列化时将不会被保存。该标识由子类继承。

                元数据修饰符
                在声明类、函数和接口时,声明上可添加元数据修饰符以控制其在引擎和编辑器的不同方面的表现。
                对元数据修饰符的使用按常规类、函数和接口修饰符而不同。
                类元数据修饰符
                BlueprintSpawnableComponent
                函数元数据修饰符
                BlueprintInternalUseOnly
                BlueprintProtected
                DeprecatedFunction
                DeprecationMessage
                UnsafeDuringActorConstruction
                接口元数据修饰符
                CannotImplementInterfaceInBlueprint
                蓝图技术指南
                蓝图编程指南
                当决定使用C++或者蓝图时,有两个主要考虑的因素
                速度
                表达式复杂度
                除了这两个因素外,其它的来自游戏的复杂程序以及团队的组成。如果你有比程序员更多的设计师,那么蓝图代码将会比C++代码多很多。相反,如果你有更多的程序员,那么他们可能更倾向于使用C++。我们(Epic)期望在这中间有一个平衡点。在Epic,大多工作流程是这样的,内容创建者会做一个非常复杂的蓝图,程序员通过C++编写一个新的蓝图节点来把前面所创建的蓝图的大部分转成C++代码,他把那部分功能转成了C++函数。一个好的经验是大量使用蓝图,然后把它转换成C++代码,当它们达到一定复杂度的时候,它需要一个关于该功能一个更精确的表达式(或者对于一个非程序员太复杂时),或者执行速度过慢需要转换成C++时。
                速度
                就速度来说,蓝图肯定会比C++慢(8~10倍见上方引用部分),并不是说性能就非常差,但是如果你做的事情需要很多的计算,或者执行频率非常高,那么最多是使用C++而不是蓝图。然而,很好地结合两者来为你们团队很好的工作和取得一个不错的性能是很有可能的。如果一个蓝图类有很多功能,那么你可以把一些功能转换成C++代码来加速,但是保留其它的部分来保证灵活性。如果你的性能分析发现蓝图中的某个操作很耗时,那么可以把那部分转移到C++,其它的保留在蓝图中。
                假如要使用蓝图来控制几千个Actor,那么这种情况下就最好用C++来处理决策、寻路等,然后把一个可调节的属性和控制函数暴露给蓝图。
                复杂度
                就表达式复杂来说,有些东西用C++来做确实比蓝图容易。蓝图在很多方面做的很好,但是有些东西在蓝图结点内却并不好表达。比如操作大量数据,字符串操作,大量数据的数学操作等都很复杂,且在一个可视化系统里面并不容易云做。这些东西最好用C++来实现,因为它们容易看出来到底在做什么。
                参考
                https://docs.unrealengine.com/latest/CHN/Gameplay/ClassCreation/CodeAndBlueprints/index.html
                https://docs.unrealengine.com/latest/CHN/Programming/UnrealArchitecture/Reference/Classes/Specifiers/index.html
                https://docs.unrealengine.com/latest/INT/Engine/Blueprints/TechnicalGuide/Guidelines/index.html
                作者: 风恋残雪
                出处: http://www.cnblogs.com/ghl_carmack
                关于作者:专注游戏引擎,关注VR,对操作系统、编译原理有深厚兴趣!
                本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接,否则保留追究法律责任的权利。


                IP属地:安徽38楼2017-03-18 16:19
                回复