本篇文章介绍如何实现如下代码的链式编程:

this.Position(Vector3.one)
.LocalScale(1.0f)
.Rotation(Quaternion.identity);

以上代码中,this 为 MonoBehaviour 类型的对象。

如何实现?

通过上篇文章介绍的 return this + 静态扩展很容易做到,实现代码如下所示:

        public static MonoBehaviour Position(this MonoBehaviour selfBehaviour, Vector3 position)
{
selfBehaviour.transform.position = position;
return selfBehaviour;
} public static MonoBehaviour LocalScale(this MonoBehaviour selfBehaviour, float xyz)
{
selfBehaviour.transform.localScale = Vector3.one * xyz;
return selfBehaviour;
} public static MonoBehaviour Rotation(this MonoBehaviour selfBehaviour, Quaternion rotation)
{
selfBehaviour.transform.rotation = rotation;
return selfBehaviour;
}

很容易实现对吧?但是这样有个问题,由于静态扩展方法返回的是 MonoBehaviour 类而不是this所属的类型,所以接下来链式方法中只能使用 MonoBehaviour 的方法。不能像如下方式使用。

            this.Position(Vector3.one)
.LocalScale(1.0f)
.Rotation(Quaternion.identity)
.DoSomething();

以上代码中,this 为 MonoBehaviour 类型的对象。

如何解决这个问题呢?答案是引入泛型。

引入泛型

实现代码如下所示:

        public static T Position<T>(this T selfBehaviour, Vector3 position) where T : MonoBehaviour
{
selfBehaviour.transform.position = position;
return selfBehaviour;
} public static T LocalScale<T>(this T selfBehaviour, float xyz) where T : MonoBehaviour
{
selfBehaviour.transform.localScale = Vector3.one * xyz;
return selfBehaviour;
} public static T Rotation<T>(this T selfBehaviour, Quaternion rotation) where T : MonoBehaviour
{
selfBehaviour.transform.rotation = rotation;
return selfBehaviour;
}

实现很简单,只是把之前代码中的 MonoBehaivour 改成泛型T,然后增加一个约束: where T : MonoBehaviour。表示这个泛型一定要继承自 MonoBehaviour。这样之前例子中的this可以使用MonoBehaviour 之外的方法实现链式编程了。

进一步完善

不只是自己实现的 MonoBehaviour 脚本像 UGUI 的 Image 等都要支持 transform 的链式编程。那么就要找到transfom 到底是哪个类?最后找到了如下代码。

namespace UnityEngine
{
/// <summary>
/// <para>Base class for everything attached to GameObjects.</para>
/// </summary>
[RequiredByNativeCode]
public class Component : Object
{
/// <summary>
/// <para>The Transform attached to this GameObject.</para>
/// </summary>
public extern Transform transform { [MethodImpl(MethodImplOptions.InternalCall)] get; }
...

最终定位到,transform 是 Component 的属性器。 所以可以将之前的实现改为如下代码:

        public static T Position<T>(this T selfComponent, Vector3 position) where T : Component
{
selfComponent.transform.position = position;
return selfComponent;
} public static T LocalScale<T>(this T selfComponent, float xyz) where T : Component
{
selfComponent.transform.localScale = Vector3.one * xyz;
return selfComponent;
} public static T Rotation<T>(this T selfComponent, Quaternion rotation) where T : Component
{
selfComponent.transform.rotation = rotation;
return selfComponent;
}

通过此种方式实现 Graphfic,Component 等类,最后可以实现如下方式的链式编程。

Image image = null;

image.LocalPosition(Vector3.back)
.ColorAlpha(0.0f)
.Hide();

当然,去查看一个属性到底是哪个类实现的这个过程也是一个很好的学习方式 : ) ,有很多类都可以实现链式编程,不过剩下的要靠大家自己了,当然也可以参考 QFramework 里的实现方式,不过 QFramework 也只是对笔者常用的类进行了实现。

OK,本篇介绍到这里。

转载请注明地址:凉鞋的笔记:liangxiegame.com

更多内容

Unity 游戏框架搭建 (十八) 静态扩展 + 泛型实现transform的链式编程的更多相关文章

  1. Unity 游戏框架搭建 (十) QFramework v0.0.2小结

    从框架搭建系列的第一篇文章开始到现在有四个多月时间了,这段时间对自己来说有很多的收获,好多小伙伴和前辈不管是在评论区还是私下里给出的建议非常有参考性,在此先谢过各位. 说到是一篇小节,先列出框架的概要 ...

  2. Unity 游戏框架搭建 (十六) v0.0.1 架构调整

    背景: 前段时间用Xamarin.OSX开发一些工具,遇到了两个问题. QFramework的大部分的类耦合了Unity的API,这样导致不能在其他CLR平台使用QFramework. QFramew ...

  3. Unity 游戏框架搭建 (十五) 优雅的QChain (零)

    加班加了三个月终于喘了口气,博客很久没有更新了,这段期间框架加了很多Feature,大部分不太稳定,这些Feature中实现起来比较简单而且用的比较稳定的就是链式编程支持了. 什么是链式编程? 我想大 ...

  4. Unity 游戏框架搭建 2019 (八) 关于导出 UnityPackage 功能的小结

    导出 UnityPackage 功能到这里要告一段落了,相信认真看的童鞋都有收获.笔者在写教程之前纠结了很久.到底是先给出一坨工具代码,然后再逐个讲解比较好,还是一篇一个知识点比较好.后来想通了.工具 ...

  5. Unity 游戏框架搭建 (十九) 简易对象池

    在Unity中我们经常会用到对象池,使用对象池无非就是解决两个问题: 一是减少new时候寻址造成的消耗,该消耗的原因是内存碎片. 二是减少Object.Instantiate时内部进行序列化和反序列化 ...

  6. Unity 游戏框架搭建 (十四) 优雅的QSignleton(零) QuickStart

      好久不见 !之前想着让各位直接用QFramework,但是后来想想,如果正在进行的项目直接使用QFramework,这样风险太高了,要改的代码太多,所以打算陆续独立出来一些工具和模块,允许各位一个 ...

  7. Unity 游戏框架搭建 (十二) 简易AssetBundle打包工具(二)

    上篇文章中实现了基本的打包功能,在这篇我们来解决不同平台打AB包的问题. 本篇文章的核心api还是: BuildPipeline.BuildAssetBundles (outPath, 0, Edit ...

  8. Unity 游戏框架搭建 2018 (一) 架构、框架与 QFramework 简介

    约定 还记得上版本的第二十四篇的约定嘛?现在出来履行啦~ 为什么要重制? 之前写的专栏都是按照心情写的,在最初的时候笔者什么都不懂,而且文章的发布是按照很随性的一个顺序.结果就是说,大家都看完了,都还 ...

  9. Unity 游戏框架搭建 (十三) 无需继承的单例的模板

    之前的文章中介绍的Unity 游戏框架搭建 (二) 单例的模板和Unity 游戏框架搭建 (三) MonoBehaviour单例的模板有一些问题. 存在的问题: 只要继承了单例的模板就无法再继承其他的 ...

随机推荐

  1. php字符集转换

    PHP通过iconv将字符串从GBK转换为UTF8字符集. 1. iconv()介绍 iconv函数可以将一种已知的字符集文件转换成另一种已知的字符集文件.例如:从GB2312转换为UTF-8. ic ...

  2. 在HTML代码中使用freemarker

    在HTML代码中使用freemarker 1.freemarker中显示某对象的属性使用${user.name}. 但如果name为null,freemarker就会报错.如果需要判断对象是否为空: ...

  3. 把getJson() 设置为同步执行

    因为业务需求,需要在获取到json 数据后,对数据进行处理. 这时候,我们需要把getJson() 的方法设置为同步 $.ajaxSettings.async = false; getJson() 方 ...

  4. GeoJSON相关操作

    简介 本文主要介绍GEOJSON相关的操作 环境 gt-geojson-.jar,jts-1.8.jar 直接上代码 代码 wkt格式的geometry转成json格式 public String e ...

  5. webgis开发-开始向JS转向

    官方的一个blog Final Release and Support Plan for the ArcGIS APIs / Viewers for Flex and Silverlight 网址: ...

  6. 十八、移动端rem布局

    使用rem布局,首先要知道自己是根据UI给的视效图的多少基准的,这里是以750px为基准,代码如下: //rem布局,此处根据750px来设置,放大100倍 (function(doc, win) { ...

  7. 动态注册broadcast的安全考虑

    一.android service通知activity更新方式有1. service 通过广播的形式发送broadcast,向这个activity的内部类发广播的消息来更新界面2. service直接 ...

  8. mybatis ${}使用注意事项

    ${key}有值, ${key,jdbcType=VARCHAR}没有值 总结:${}使用时不要指定jdbcType等属性,指定这些反而取不到值,这也是跟#{}的一个区别.以上只是开发中遇到的情况,具 ...

  9. MYSQL连接相关参数和状态值详解

    针对mysql的连接参数和状态值,本文做些介绍和对比 一.MYSQL连接参数变量 1.常用连接数限制参数 show variables like '%connect%'; | max_connect_ ...

  10. java excel转pdf 工具类

    package com.elitel.hljhr.comm.web.main.controller; import java.io.File; import java.io.FileOutputStr ...