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

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. spring下应用@Resource, @Autowired 和 @Inject注解进行依赖注入的差异

    为了探寻 '@Resource', '@Autowired', 和'@Inject'如何解决依赖注入中的问题,我创建了一个"Party"接口,和它的两个实现类"Perso ...

  2. android popupwindow位置显示

    1.在控件的上方: private void showPopUp(View v) { LinearLayout layout = new LinearLayout(this); layout.setB ...

  3. 【JAVA语法】01Java-变量与数据类型

    数据类型初阶 基本数据类型的包装类 整数类型&浮点类型&字符类型 大小类型转换 通过Scanner从控制台获取数据 变量相关基础算法 Java的错误类型 字符串String 补充-Pa ...

  4. AS开发实战第二章学习笔记——其他

    第二章学习笔记(1.19-1.22)像素Android支持的像素单位主要有px(像素).in(英寸).mm(毫米).pt(磅,1/72英寸).dp(与设备无关的显示单位).dip(就是dp).sp(用 ...

  5. js 时间格式化 (兼容safari)

    js 时间格式化,兼容IE8和safari浏览器. function formatDate(date, fmt, near, type) { var dateStr = date; if (!date ...

  6. c# 值类型与引用类型(转)

    本文意在巩固基础知识,并不是对其进行深入剖析,还望理解.本文是对此项知识的整理文,有些内容来源于网络,其他为博主原创,所以难免会有一些小得瑕疵,敬请谅解.所有示例均是博主测试过的,如有转载请标明出处, ...

  7. Linux 虚拟机中配置 GNOME + VNC

    需求描述 在特定的需求下,需要用到 Linux 的图形化界面,但是 Azure 平台提供的虚拟机默认没有开放远程图形化登陆的功能.以下解决方案,提供了市面上非常流行的 GNOME + VNC 的组合来 ...

  8. div浮层,滚动条移动,保持位置不变的4种方法

    div浮层,滚动条移动,保持位置不变的4种方法 div在顶部不变.滚动条滚动,div还是在顶部! 直接上传源码 了: 方法一: <!DOCTYPE html PUBLIC "-//W3 ...

  9. 使用Powershell 管理 Windows 2012 hyper-v复制

    HyperV复制相关命令 Suspend-VMReplication Suspends replication of a virtual machine. 暂停复制虚拟机. Resume-VMRepl ...

  10. July 11th 2017 Week 28th Tuesday

    No possession, but use, in the only riches. 真正的财富不是占有,而是使用. These days I have bought tens of books a ...