Mark: Mono 的 AOT 模式类似于静态编译.

Mono在Full AOT模式下的限制
调试时遇到一个Mono运行时异常:

ExecutionEngineException: Attempting to JIT compile method ‘…’ while running with –aot-only.

最后发现原因是使用了泛型接口,导致Mono需要JIT编译,但在iOS平台中,Mono是以Full AOT模式运行的,无法使用JIT引擎,于是引发了这个异常。

Mono的AOT和.NET的Ngen一样,都是通过提前编译来减少JIT的工作,但默认情况下AOT并不编译所有IL代码,而是在优化和JIT之间取得一个平衡。由于iOS平台禁止JIT编译,于是Mono在iOS上需要Full AOT编译和运行。即预先对程序集中的所有IL代码进行AOT编译生成一个本地代码映像,然后在运行时直接加载这个映像而不再使用JIT引擎。目前由于技术或实现上的原因在使用Full AOT时有一些限制,具体可以参考MonoTouch的文档,这里提几条常见的:

不支持泛型虚方法,因为对于泛型代码,Mono通过静态分析以确定要实例化的类型并生成代码,但静态分析无法确定运行时实际调用的方法(C++也因此不支持虚模版函数)。
不支持对泛型类的P/Invoke。
目前不能使用反射中的Property.SetInfo给非空类型赋值。
值类型作为Dictionary的Key时会有问题,实际上实现了IEquatable的类型都会有此问题,因为Dictionary的默认构造函数会使用EqualityComparer.Default作为比较器,而对于实现了IEquatable的类型,EqualityComparer.Default要通过反射来实例化一个实现了IEqualityComparer的类(可以参考EqualityComparer的实现)。 解决方案是自己实现一个IEqualityComparer,然后使用Dictionary(IEqualityComparer)构造器创建Dictionary实例。
由于不允许动态生成代码,不允许使用System.Reflection.Emit,不允许动态创建类型。
由于不允许使用System.Reflection.Emit,无法使用DLR及基于DLR的任何语言。
不要混淆了Reflection.Emit和反射,所有反射的API均可用。
– See more at: http://ravenw.com/blog/2011/11/08/limitations-of-mono-with-full-aot/#sthash.JPliz7km.dpuf

Read More

使用TexturePacker 制作动画的贴图 导出在 SpriteKit 中使用.SpriteKit Animations and TextureAtlasses,Use TexturePacker.

作为经常使用的工具, TexturePacker的确是很方便的打包贴图的工具. 打包可以减少DrawCall次数.对于提升性能有很大作用.而且作者很友好,如果是开发阶段使用, 可以申请免费的授权. 当然,如果产品赚了钱都应该买一份正版.SpriteKit是ios7新的特性,为2D游戏开发而做, TexturePacker也推出了一个示范的实现,整合在一起. 工具化,制作流程规范化是趋势. 你out了么.

ios7 SpriteKit 开发者指南. http://upyun.cocimg.com/cocoachina/SpriteKit_PG.pdf

TexturePacker 下载: http://www.codeandweb.com/texturepacker/download

支持的真多啊: Cocos2d SpriteKit Corona SDK Starling Unity3D Flash / AS3 CSS / HTMLLibGDX AndEngine Moai Cocos2d-X XNA PlayStation® Suite V-Play

SpriteKit Animations and TextureAtlasses

http://www.codeandweb.com/blog/2013/09/23/spritekit-animations-and-textureatlasses

使用TexturePacker 制作动画的贴图 导出在 SpriteKit 中使用.

The main advantages over the pure Xcode solution are

  • Organizing your sprites in folders
  • Importing multiple formats such as PNG, PSD, SVG, SWF
  • Compile time checks for sprite names
  • Creating animations with a single line of code

纯Xcode的优点:  在目录里自己组织Sprites /可以同时导入各种格式. png psd  svg swf / 编译时检查sprite 资源名字 /一行代码完成动画创建.

Let’s start with how to easily create your atlas.

下面就开始示范如何创建 atlas

Create your SpriteKit atlas with TexturePacker

To create a new SpriteKit atlas, simply start TexturePacker and drag & drop the directories containing your sprite images to the Sprites area of TexturePacker. TexturePacker will automatically load and lay out all image files:

拖拽sprites文件夹到 TexturePacker 窗口即可. 导入资源. 如下图.

Select SpriteKit in the Data Format field, and enter a path to which the atlas bundle should be written. Parallel to this .atlasc file TexturePacker generates a .h header file which contains useful macros for easy SKTexture creation. If you choose the Xcode project directory as output here, the generated header file is automatically found in the include path.

选择导出格式. 设置导出路径以及导出的模板. 推荐导出到Xcode的工程目录里面. 直接就可以include 了.

To use the published sprite sheet in Xcode, drag and drop the .atlasc bundle and the generated .h header file to your Xcode project:

导出后, 需要加入  .atlasc  .h 文件到工程里. 方法如下, 拖拽到Xcode 的窗口里.

Xcode asks how the folder should be added. If you create a folder reference, the Xcode project is automatically updated in the future if the altascbundle changes (e.g. additional sprite sheets are added).

然后, 在对话框里, 选择 create folder references for any added fodlers   以及 确认  add to targets 选中.  这样资源文件才会在打包时包含到App里.

Creating a SKSpriteNode from the texture atlas

演示使用 textureAtlas 创建. SKSpriteNode

Creating a textured sprite is quite easy, just load the texture and use the SKTexture object when creating the sprite node:

很简单就是用 SKTexture

texture = [SKTexture textureWithImageNamed:@"Background"];
sprite = [SKSpriteNode spriteNodeWithTexture:texture];

The first line loads the sprite—looking for a single sprite in the file system— and if not found searching all sprite sheets available to the application.

The second line creates a sprite object using the specified texture.

Adding compile-time checks to your SpriteKit project

As the texture image is referenced by its file name, typos in its name or a mismatch due to a reorganized texture atlas cannot be detected at compile-time.

因为texture 是一个文件名. 所以没办法在编译时检查某些贴图资源不存在的情况. 毕竟这是逻辑状态. 比如 “button1”  你可以用不存在的贴图资源创建对象. 只有运行时才会报错. 编译时检查不出来的.

TexturePacker 提供了一个变通的解决方法. 引入了一个头文件  如果你使用了不存在的资源名字. 就会报错了. 当然也需要你使用常量去创建对象. 比如  __BUTTON__ 而不是 “button1“ 后者的话还是会有问题的.

SpriteKit replaces missing images with a dummy graphic which might look strange. Imagine what this would mean for you if it accidently reaches the AppStore…

TexturePacker helps you avoid this: with compile-time checks!

TexturePacker creates a header file together with your atlas. You can simply import it using:

#import "sprites.h"

The file contains all sprite names used in the atlas as a #define. It also defines a macro for each texture image which creates the corresponding SKTexture object.

#define SPRITES_SPR_BACKGROUND       @"Background"
#define SPRITES_SPR_CAPGUY_TURN_0001 @"capguy/turn/0001"
#define SPRITES_SPR_CAPGUY_TURN_0002 @"capguy/turn/0002"
...
#define SPRITES_TEX_BACKGROUND       [SKTexture textureWithImageNamed:@"Background"]
#define SPRITES_TEX_CAPGUY_TURN_0001 [SKTexture textureWithImageNamed:@"capguy/turn/0001"]
#define SPRITES_TEX_CAPGUY_TURN_0002 [SKTexture textureWithImageNamed:@"capguy/turn/0002"]

Using these defines, creating a sprite is a 1-liner:

通过定义好的头文件创建 SKSpriteNode  即 Sprite 我们需要的动画精灵.

SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithTexture:SPRITES_TEX_BACKGROUND];

If you now rename the sprite and publish the sprite atlas from TexturePacker, the definition also changes its name. When compiling in Xcode you get a compiler error about a missing sprite.

注意: 如果你修改了定义的名字. 会有编译错误.  需要手动修改成新的动画的名字. (老的被删除了)

Simplifying SpriteKit’s animation handling

Sprites are considered as animation if they end with a number—e.g. img_01img_02, etc. For these an NSArray object with all textures of the animation is defined.

#define SPRITES_ANIM_CAPGUY_TURN @[ 
        [SKTexture textureWithImageNamed:@"capguy/turn/0001"], 
        [SKTexture textureWithImageNamed:@"capguy/turn/0002"], 
        [SKTexture textureWithImageNamed:@"capguy/turn/0003"], 
        ...
SKSPrite 用数组来管理帧. 如上.

This makes it extremely simple to animate sprites:

SKAction *walk = [SKAction animateWithTextures:SPRITES_ANIM_CAPGUY_WALK timePerFrame:0.033];
[sprite runAction:walk];
初始化一个动画Action 如上. SKAction 是一组动画帧. 代表一个状态. 比如walk.

No more adding single frames, no more worrying about missing animation phases!

Enhancing the animation with additional frames—or removing frames—doesn’t require you change the code at all: TexturePacker always fills in the right frames.

Using SKActions to move the sprite

用SKActions 来移动sprite吧.

For our sample application we use two animations:

  • walk (left to right)
  • turn (right to left)

These animations can be created as mentioned above:

SKAction *walk = [SKAction animateWithTextures:SPRITES_ANIM_CAPGUY_WALK timePerFrame:0.033];
SKAction *turn = [SKAction animateWithTextures:SPRITES_ANIM_CAPGUY_TURN timePerFrame:0.033];

Due to the enormous width of the iPad display we have to repeat the animation a few times:

SKAction *walkAnim = [SKAction sequence:@[walk, walk, walk, walk, walk, walk]];
用重复的Action 实现新的组合动画.. 如上.. walk ,walk ...
Note As SpriteKit does not allow repeat actions to be nested, we cannot use [SKAction repeatAction:count:] here, this would conflict with [SKAction repeatActionForever:], see below. This is why we implement the action as a sequence of walk actions.
注意: 因为 SpriteKit 不允许 重复的actions 被嵌套循环.
In the animation CapGuy walks without moving forward. We need a move action to move the sprite from left to right, and back. The action gets the same duration as the animation itself:
SKAction *moveRight  = [SKAction moveToX:900 duration:walkAnim.duration];
SKAction *moveLeft   = [SKAction moveToX:100 duration:walkAnim.duration];

We have only an animation with CapGuy walking from left to right, but not in the other direction. So we use a scale action with scaling factor -1 to get a mirrored animation. Another action is needed to set the scaling back to 1:

SKAction *mirrorDirection  = [SKAction scaleXTo:-1 y:1 duration:0.0];
SKAction *resetDirection   = [SKAction scaleXTo:1  y:1 duration:0.0];

All action which are put into a group are executed in parallel. We are not only adding the walk and move actions to a group, but also the mirror /reset actions. They have a duration of 0 and are executed at the beginning of the group, so their scaling factor has direct impact on the walk /move actions:

所有的action 是并行执行的. 通过在开头加入 mirror/reset 来实现改变方向.

SKAction *walkAndMoveRight = [SKAction group:@[resetDirection,  walkAnim, moveRight]];
SKAction *walkAndMoveLeft  = [SKAction group:@[mirrorDirection, walkAnim, moveLeft]];

Now we combine walkturn actions into a sequence, and repeat this sequence forever:

self.sequence =
  [SKAction repeatActionForever:[SKAction sequence:@[walkAndMoveRight, turn, walkAndMoveLeft, turn]]];
上面我们把走和转向混合起来.然后一直执行它.

Applying SKAction to multiple SKSpriteNodes

SKAction objects can be used for many sprites in parallel. In our example we want to create a new CapGuy sprite each time the user touches the screen. We have to create a new SKSpriteNode only, and run the action on it which we created in the section above:

SKAction作为数据可以给多个SKSPrite对象来使用. 下面的例子实现了 每次点击 新建一个自动走的精灵的.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithTexture:SPRITES_TEX_CAPGUY_WALK_0001];
    sprite.position = CGPointMake(100, rand() % 100 + 200);

    [sprite runAction:sequence];
    [self addChild:sprite];
}

The complete SpriteKit sample

如图,你可以看到很多精灵人物走来走去.

Source code available for download

The source code is available on GitHub. Either clone it using git:

Read More

Unity Network Programming Useful Link

Tutorials on Photon, Unity and Networking

List of third party tutorials on Photon Cloud, Photon Server, Unity 3D and Networking

Photon Tutorials

General Networking Tutorials

Unity Networking Tutorials

Unity Tutorials

  • Tutorials section on Unity website, currently there are beginner’s tutorials only, but more are coming
  • Collection of video lessons for beginner and intermediate Unity developers, includes challenges and examples
  • Another collection of various Unity tutorials from Unity Cookie
  • Video tutorials on various Unity 3 topics from Technicat
  • Big list of tutorials on Unity, including game making, labs and exams from Walker Boys studio
  • UnityGems, tutorials on Basics, AI, Shaders and Finite State Machines written by contributors to Unity Answers and Unity Forums

Read More

被ios7bug,基于api的接口都是脆弱的.

此次ios7发布. 总体感觉,比ios6 ios5升级时颠覆感要强烈很多.

进而带来的就是老项目代码升级问题.

显然 作为开发应用的支持, apple 做了功课. 比如分辨率 透明statusbar处理等, 挖掘一下以后, app开发应该是可以无痛升级的. 核心代码不用改.

而游戏项目, 我们用了cocos2dx 的游戏就有点悲催, 会在ios7上闪退.  track了一番, 最后是 CCFileUtils 取路径的函数的bug. 真不知道ios7改动了啥. getfullpath 需要传入一个存在的文件名.

已经上架了的project,  至少还得重新patch compile 再提交一次..   用了cocos2dx 这么久了也有些要吐槽的, 接口差异变化挺大. 文件名改动. 换位置..各种… 冷不丁要从一旧版本升级到新版,还真有些小折腾.

跑题了, 回到标题.  ios7升级是个新的知识点. 初期没有太多可以google到的. 所以要么自己动手,要么等待..   没有项目压力的话, 还好. 否则, 你想象一下.  而基于ios api 的 api 就有可能随着底层变更而变得有些bug. 是被bug的.

而Apple显然也没进行额外的测试和支持?  只是保证了大多数情况下是ok的.

对于处理升级中遇到的问题,  其实, 如果平日你积累了人脉. 问一圈下来,大概也就有数了. 大方向不会错.

我总结如下

xcode4.6 编译也是可以跑在 ios7上的. 所以最快的方式先修了闪退的bug.  然后更新.

xcode5编译还有一些诡异的问题等着我们.   暂时可以放一放. 慢慢过渡到2.2.0 纯ios7. 新项目应该用新版本.

还有一个伴随的扰乱视线的bug,   Project里面资源文件夹  蓝色和黄色图标的区别是在 App 包里是否创建同样的目录.. 真蛋疼.    黄色的 你用了带目录的路径就找不到文件…

Read More

官方 Scaleform 文档资料和教程 链接

官方 Scaleform 文档资料和教程
  • Scaleform UDK 文档资料 – 官方 Scaleform 4.0 UDK 文档资料。
  • 导入 SWF – 这个视频讨论的是创建 Flash 内容并将其导入到 UDK 中的一些重要规则。
  • 渲染贴图 & 材质 – 这个视频讨论的是中创建对于将交互 Flash 内容显示在 UDK 关卡中的 BSP 表面上所必需的渲染贴图和材质。
  • 将 SWF 添加到 BSP 对象 – 在这个视频中,我们谈到了将一个 Flash 文件添加到一个 BSP 表面上所需要进行的步骤,其中包括必需的 Kismet 工作流程。
  • 捕获输入 – 在这个视频中,我们说明了如何使用 GFx 捕获按键 kismet 节点将键盘和游戏控制器输入传输到 Flash 文件中。这样它会解释说明这个输入,然后使您可以旋转 3D 中的视频剪辑。
  • 使用 Invoke ActionScript & FSCommands – 在这个视频中,我们谈到了 Invoke ActionsCript 在 Kismet 中的使用,它允许您通过 UDK 调用 Flash 文件中的 ActionScript 函数。我们还将谈到通过 FS Commands 将一个命令从这个 Flash 文件中发送返回到 UDK。
  • 创建自定义菜单 – 在第六个 UDK 视频教程中,我们将会向您说明如何使用 Scaleform GFx 和 UnrealScript 创建一个自定义菜单系统的基础内容。
  • 使用 Scaleform 3Di Flash AS2 Extensions 创建 3D UI – 这个视频将会说明如何在 Scaleform GFx 3.2 及更高版本中使用我们的新 3Di ActionScript 2 插件平移和旋转 3D 空间中的视频剪辑。
  • 处理字体 – 在第七个 UDK 视频教程中,我们将会向您说明在 Flash 及 2010 年 9 月 UDK 版本中正确使用字体需要了解的所有内容。
  • 掌握 Scaleform HUD
    1. HUD 概述 – 这是由四部分组成的系列中的第一部分,它将会带您浏览 2010 年 9 月 UDK Scaleform HUD 中的所有文件和资源。
    2. UTGFxHudWrapper.uc – 这是说明 2010 年 9 月 UDK Scaleform HUD 是如何组成的第二个视频。在这个视频中,我们全面介绍了 UTGFxHudWrapper.uc 类的基础构成,同时我们花了一段时间详细说明了如何打开和关闭暂停菜单作为 HUD 的一部分。
    3. GFxMinimapHud.uc – 第 1 部分 – 这是说明 2010 年 9 月 UDK Scaleform HUD 是如何组成的第三个视频。在这个视频,我大致介绍了 GFxMinimapHud 类的前半部分内容以及 udk_hud Flash 文件。
    4. GFxMinimapHud.uc – 第 2 部分 – 这是说明 2010 年 9 月 UDK Scaleform HUD 是如何组成的第四个视频。在这个视频中,我对 GFxMinimapHud 类的后半部分内容进行了说明。
  • CLIK 入门指南
    1. 初始设置 – 在这个教程中,我们将会向您说明如何使用这个新的组件精简接口工具包或 CLIK 快速设计基础前端菜单系统,它将会包含一个主菜单和一个选项画面,全部由核心 CLIK 组件组成,例如按钮、滑块、选项步进以及单选按钮。
    2. 主菜单设置 – 在第二个步骤中,我们将会向主菜单中添加一些基本功能。
    3. 创建选项画面 – 在第三步骤中,我们会让主菜单上的按钮可以将用户带入到选项画面,我们也会添加一个与我们的第一个选项相同的难度设置选项步长。
    4. 复选框、单选按钮 & 滑块 – 在第四个步骤中,我们会添加一些新的组件,其中包括视频设置复选框、单选按钮以及音量滑块。
    5. 添加功能 – 在第五个步骤中,我们会添加 ok(确定)和 cancel(取消)按钮,同时会对难度设置选项步长和单选按钮添加一些功能。
    6. 保留更改 – 在第六个步骤中,我们会设置选项画面,这样它才会在按下 OK 按钮后保留用户所进行的任何更改。
    7. 添加背景 – 在这个教程中,我们会向您说明如何为那些组成我们在教程 1-6 中创建的菜单的组件更换皮肤。我们会将这个过程划分为八个步骤。在步骤中,我们会向这个菜单添加一个背景图片。
    8. 导入背景 – 在这个步骤中,我们会导入在 Adobe Photoshop 中创建的图片作为我们的选项画面的窗口使用。我们还会调整组件使它们与窗口相适应,然后复制一个组件,这样我们就有它的两个不同皮肤的版本了。
    9. 为主菜单按钮更换皮肤 – 在这个步骤中,我们将会为主菜单按钮更换皮肤。
    10. 为 OK 和 Cancel 按钮更换皮肤 – 在步骤 10 中,我们将会为 ok 和 cancel 按钮更换皮肤。
    11. 为声音滑块更换皮肤 – 步骤 11 将会涉及为声音滑块更换皮肤。
    12. 为复选框更换皮肤 – 我们将会在步骤 12 中为复选框更换皮肤。
    13. 为单选按钮更换皮肤 – 我们将会在这个步骤中为视频设置单选按钮更换皮肤。
    14. 为选项步长更换皮肤 – CLIK 入门指南中的最后一个步骤将会涉及未难度选项步长更换皮肤。
  • Scaleform 用户界面设计 – 在 MIGS 2011 举行的虚幻学院上 Matt Doyle 进行现场演示。

Read More

Event in C#

Just to add to the existing great answers here – building on the code in the accepted one, which uses a delegate void MyEventHandler(string foo)…

Because the compiler knows the delegate type of the SomethingHappened event, this:

myObj.SomethingHappened += HandleSomethingHappened;
Is totally equivalent to:

myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);
And handlers can also be unregistered with -= like this:

// -= removes the handler from the event’s list of “listeners”:
myObj.SomethingHappened -= HandleSomethingHappened;
For completeness’ sake, raising the event can be done like this, only in the class that owns the event:

//Firing the event is done by simply providing the arguments to the event:
if (SomethingHappened != null) // the event is null if there are no listeners!
{
SomethingHappened(“Hi there!”);
}

Read More

Recheck the words and grammar that you previously checked and chose to ignore

Recheck the words and grammar that you previously checked and chose to ignore

In Word and Outlook, you can force a recheck of the words and grammar that you previously choose to ignore by doing the following:

Word

  1. Open the document that needs to be checked.
  2. Click the File tab.
  3. Under Help, click Options.
  4. Under Correcting spelling and grammar in Word, click Recheck Document.
  5. To recheck the spelling and grammar, click Yes when you see the following message: This operation resets the spelling checker and the grammar checker so that Word will recheck words and grammar you previously checked and chose to ignore. Do you want to continue?
  6. In the Word Options dialog box, click OK to get back to the document.
  7. On the Review tab, in the Proofing group, click Spelling & Grammar.

Read More

给你5个写blog的理由

●  写你感兴趣的东西,不必在意你是否是专家
●  不要害怕失败
●  多多回复你的读者
●  就算你觉得没人会看你写的东西,也要坚持写下去
●  始终确保你的文章就代表着你的声音——这也是为什么写作是如此特别和吸引人的地方

Read More

Find back svn: Using External Version Control Systems with Unity

Using External Version Control Systems with Unity

Unity offers an Asset Server add-on product for easy integrated versioning of your projects. If you for some reason are not able use the Unity Asset Server, it is possible to store your project in any other version control system, such as Subversion, Perforce or Bazaar. This requires some initial manual setup of your project.

Before checking your project in, you have to tell Unity to modify the project structure slightly to make it compatible with storing assets in an external version control system. This is done by selecting Edit->Project Settings->Editor in the application menu and enabling External Version Control support by selecting Metafiles in the dropdown for Version Control. This will create a text file for every asset in the Assets directory containing the necessary bookkeeping information required by Unity. The files will have a.meta file extension with the first part being the full file name of the asset it is associated with. Moving and renaming assets within Unity should also update the relevant.meta files. However, if you move or rename assets from an external tool, make sure to syncronize the relevant .meta files as well.

When checking the project into a version control system, you should add the Assets and the ProjectSettings directories to the system. The Library directory should be completely ignored – when using external version control, it’s only a local cache of imported assets.

When creating new assets, make sure both the asset itself and the associated .meta file is added to version control.

Example: Creating a new project and importing it to a Subversion repository.

First, let’s assume that we have a subversion repository at svn://my.svn.server.com/ and want to create a project at svn://my.svn.server.com/MyUnityProject. Then follow these steps to create the initial import in the system:

  1. Create a new project inside Unity and call it InitialUnityProject. You can add any initial assets here or add them later on.
  2. Enable Meta files in Edit->Project Settings->Editor
  3. Quit Unity (this ensures that all the files are saved).
  4. Delete the Library directory inside your project directory.
  5. Import the project directory into Subversion. If you are using the command line client, this is done like this from the directory where your initial project is located:
    svn import -m"Initial project import" InitialUnityProject svn://my.svn.server.com/MyUnityProject
    If successful, the project should now be imported into subversion and you can delete the InitialUnityProject directory if you wish.
  6. Check out the project back from subversion
    svn co svn://my.svn.server.com/MyUnityProject
    And check that the Assets and ProjectSettings directory are versioned.
  7. Open the checked out project with Unity by launching it while holding down the Option or the left Alt key. Opening the project will recreate the Library directory in step 4 above.
  8. Optional: Set up an ignore filter for the unversioned Library directory:
    svn propedit svn:ignore MyUnityProject/
    Subversion will open a text editor. Add the Library directory.
  9. Finally commit the changes. The project should now be set up and ready:
    svn ci -m"Finishing project import" MyUnityProject

Page last updated: 2013-05-15

Read More