﻿<?xml version="1.0" encoding="utf-8"?>
<rss
  version="2.0">
  <channel>
    <title>Blog of Icarus</title>
    <link>http://cabinicarus.com/</link>
    <description />
    <lastBuildDate>Fri, 08 Mar 2024 21:43:26 +0800</lastBuildDate>
    <item>
      <guid
        isPermaLink="false">http://cabinicarus.com/posts/dota2-动态触发区</guid>
      <link>http://cabinicarus.com/posts/dota2-%E5%8A%A8%E6%80%81%E8%A7%A6%E5%8F%91%E5%8C%BA</link>
      <title>DOTA2 - 动态触发区</title>
      <description>&lt;p&gt;前期准备工作:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;各种类型的触发区模型&lt;code&gt;.vmdl&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里是一个内置的内置的盒子基础模型的文件内容，可以保存为&lt;code&gt;.vmdl&lt;/code&gt;查看效果,可以看出文件是&lt;code&gt;kv3&lt;/code&gt;格式的,也就意味着可以编写工具来批量生成这些模型文件&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;!-- kv3 encoding:text:version{e21c7f3c-8a33-41c5-9977-a76d3a32aa0d} format:modeldoc32:version{c5dcef98-b629-46ab-88e3-a17c005c935e} --&amp;gt;
{
	rootNode = 
	{
		_class = &amp;quot;RootNode&amp;quot;
		children = 
		[
			{
				_class = &amp;quot;PhysicsShapeList&amp;quot;
				children = 
				[
					{
						_class = &amp;quot;PhysicsHullFromRender&amp;quot;
						parent_bone = &amp;quot;&amp;quot;
						surface_prop = &amp;quot;default&amp;quot;
						collision_prop = &amp;quot;default&amp;quot;
						faceMergeAngle = 20.0
						maxHullVertices = 32
						optimization_algorithm = &amp;quot;IFR&amp;quot;
					},
				]
				leave_body_collision_unmodified = false
			},
			{
				_class = &amp;quot;RenderMeshList&amp;quot;
				children = 
				[
					{
						_class = &amp;quot;RenderPrimitiveBox&amp;quot;
						name = &amp;quot;box&amp;quot;
						parent_bone = &amp;quot;&amp;quot;
						material_name = &amp;quot;dev/helper/testgrid.vmat&amp;quot;
						origin = [ 0.0, 0.0, 0.0 ]
						angles = [ 0.0, 0.0, 0.0 ]
						max_u = 1.0
						max_v = 1.0
						dimensions = [ 100.0, 100.0, 100.0 ]
						segments_x = 1
						segments_y = 1
						segments_z = 1
					},
				]
			},
		]
		model_archetype = &amp;quot;&amp;quot;
		primary_associated_entity = &amp;quot;&amp;quot;
		anim_graph_name = &amp;quot;&amp;quot;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="section"&gt;如何创建触发区&lt;/h2&gt;
&lt;p&gt;在Lua那边编写,下面的代码时&lt;code&gt;ts&lt;/code&gt;的语法&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-ts"&gt;
//创建触发器实体
const trigger = SpawnEntityFromTableSynchronous('trigger_dota', {
                    targetname : DoUniqueString(&amp;quot;testTrigger&amp;quot;),
                    //坐标
                    origin     : origin,
                    //这里时对应锤子编辑器里可以编辑的字段
                    //在锤子中可以编辑的理论都可以在这里设置,如angles,scales,teamnumber,invert_filter_check等等
                    IsRealHero : 1,
                    // 这里就是触发区的模型路径
                    model : &amp;quot;models/cube200.vmdl&amp;quot;,
                    wait : 0.1,
                }) as CBaseTrigger;
                
//创建私有的脚本空间,理论应该时可以直接trigger[&amp;quot;xxx&amp;quot;] = function的,不过我自己测试没通过
const scope = trigger.GetOrCreatePrivateScriptScope();
scope[&amp;quot;OnEnter&amp;quot;] = (arg:
{
    //触发者
    activator:CDOTA_BaseNPC,
    //触发器
    caller:CBaseTrigger
}) =&amp;gt; 
{
  print(arg.activator.GetName(), &amp;quot;进入触发区!!!!!!&amp;quot;);
}

scope[&amp;quot;OnExit&amp;quot;] = (arg:
{
    //触发者
    activator:CDOTA_BaseNPC,
    //触发器
    caller:CBaseTrigger
}) =&amp;gt; 
{
  print(arg.activator.GetName(), &amp;quot;离开触发区!!!!!!&amp;quot;);
}

//连接触发区触发的io事件
trigger.RedirectOutput(&amp;quot;OnStartTouch&amp;quot;, &amp;quot;OnEnter&amp;quot;, trigger);
//连接触发区离开的io事件
trigger.RedirectOutput(&amp;quot;OnEndTouch&amp;quot;, &amp;quot;OnExit&amp;quot;, trigger);

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样动态触发区的核心就完成了！&lt;/p&gt;
&lt;p&gt;查看触发区的坐标和触发区的实际范围,可以在控制台输入&lt;code&gt;showtriggers&lt;/code&gt;，触发区会已一个绿色的形状出现，如果在非空地图里查看,可能会看到很多。&lt;/p&gt;
&lt;h3 id="section-1"&gt;小记&lt;/h3&gt;
&lt;p&gt;但是需要注意处理多个触发区交接的问题, 避免一些逻辑问题,可能需要一个计数来保证触发和离开的处理是安全的&lt;/p&gt;
&lt;p&gt;我自己在&lt;a href="https://steamcommunity.com/sharedfiles/filedetails/?id=3158547760"&gt;IcDota&lt;/a&gt;中有使用场景,游戏里每隔一段时间或击杀肉山会加载一个世界效果,我称其为动态场景(虽然和动态场景不沾边,哈哈)。&lt;/p&gt;
&lt;p&gt;欢迎体验 &lt;a href="https://steamcommunity.com/sharedfiles/filedetails/?id=3158547760"&gt;IcDota&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Fri, 08 Mar 2024 21:43:26 +0800</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="false">http://cabinicarus.com/posts/webpack全局变量方法</guid>
      <link>http://cabinicarus.com/posts/webpack%E5%85%A8%E5%B1%80%E5%8F%98%E9%87%8F%E6%96%B9%E6%B3%95</link>
      <title>webpack全局变量/方法</title>
      <description>&lt;ol&gt;
&lt;li&gt;变量从&lt;code&gt;var xxxx = xxxx&lt;/code&gt;改成&lt;code&gt;global.xxxx = xxxx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;方法则写一个&lt;code&gt;global.xxxxFunc = xxxxFunc; &lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这样修改,其他地方就不需要改了&lt;/p&gt;
</description>
      <pubDate>Thu, 14 Apr 2022 10:23:58 +0800</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="false">http://cabinicarus.com/posts/unity-粒子使用记录</guid>
      <link>http://cabinicarus.com/posts/unity-%E7%B2%92%E5%AD%90%E4%BD%BF%E7%94%A8%E8%AE%B0%E5%BD%95</link>
      <title>Unity 粒子使用记录</title>
      <description>&lt;ol&gt;
&lt;li&gt;运行时旋转粒子 &lt;a href="https://forum.unity.com/threads/problem-to-rotate-a-particle.512920/#post-3356477"&gt;官方贴&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;我一开始一直用的是&lt;code&gt;main.startRotationMultiplier&lt;/code&gt;,但是在每帧更新时,因为生命周期较长,会一卡一卡的,需要使用&lt;code&gt;GetParticles&lt;/code&gt;和&lt;code&gt;SetParticles&lt;/code&gt;方法修改&lt;code&gt;ParticleSystem.Particle&lt;/code&gt;的&lt;code&gt;rotation&lt;/code&gt;属性&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class="language-C#"&gt;private ParticleSystem _particle;
NativeArray&amp;lt;ParticleSystem.Particle&amp;gt; temp = new NativeArray&amp;lt;ParticleSystem.Particle&amp;gt;(1,Allocator.Temp);
                
_particle.GetParticles(temp);

var particle = temp[0];

particle.rotation = _angleOffset + this.transform.eulerAngles.y;
temp[0]              = particle;

_particle.SetParticles(temp); 
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Wed, 06 Apr 2022 19:20:58 +0800</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="false">http://cabinicarus.com/posts/获取在其他`custompropertydrawer`中获取`custompropertydrawer`进行自定义绘制</guid>
      <link>http://cabinicarus.com/posts/%E8%8E%B7%E5%8F%96%E5%9C%A8%E5%85%B6%E4%BB%96%60custompropertydrawer%60%E4%B8%AD%E8%8E%B7%E5%8F%96%60custompropertydrawer%60%E8%BF%9B%E8%A1%8C%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%98%E5%88%B6</link>
      <title>在其他CustomPropertyDrawer中获取CustomPropertyDrawer进行自定义绘制</title>
      <description>&lt;p&gt;然后写了个下面的Helper类,需要配合&lt;code&gt;Friend&lt;/code&gt;使用,如果创建&lt;code&gt;Unity Friend&lt;/code&gt;可以看这里&lt;a href="https://github.com/XINCGer/UnityToolchainsTrick/tree/main/Assets/Editor/Examples/Example_49_Friend"&gt;&lt;code&gt;UnityToolchainsTrick/Example_49_Friend&lt;/code&gt;&lt;/a&gt;,当然也可以反射.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-c#"&gt;//Create: Icarus
//ヾ(•ω•`)o
//2022-03-18 11:13
//Unity.InternalAPIEngineBridge.024

using System;
using System.Linq;
using System.Reflection;
using UnityEditor;

namespace CabinIcarus.EditorFrame.UnityBind
{
    public static class PropertyDrawerHelper
    {
        public static PropertyDrawer CreatePropertyDrawer(FieldInfo fieldInfo)
        {
            var types = TypeCache.GetTypesWithAttribute&amp;lt;CustomPropertyDrawer&amp;gt;();

            var drawType = types.FirstOrDefault(x =&amp;gt;
            {
                var attr = x.GetCustomAttributes&amp;lt;CustomPropertyDrawer&amp;gt;();
                
                foreach (var drawer in attr)
                {
                    if (drawer.m_Type == fieldInfo.FieldType || (drawer.m_UseForChildren &amp;amp;&amp;amp; drawer.m_Type.IsAssignableFrom(fieldInfo.FieldType)))
                    {
                        return true;
                    }
                }
                
                return false;
            });

            if (drawType != null)
            {
                var ins = (PropertyDrawer) Activator.CreateInstance(drawType);
                ins.m_FieldInfo = fieldInfo;
                return ins;
            }

            return null;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Fri, 18 Mar 2022 15:56:46 +0800</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="false">http://cabinicarus.com/posts/使用editorscript创建预制体变体</guid>
      <link>http://cabinicarus.com/posts/%E4%BD%BF%E7%94%A8editorscript%E5%88%9B%E5%BB%BA%E9%A2%84%E5%88%B6%E4%BD%93%E5%8F%98%E4%BD%93</link>
      <title>使用EditorScript创建预制体变体</title>
      <description>&lt;p&gt;如何使用友元进行Unity内部API访问的方法,可以看我在这个&lt;a href="https://github.com/XINCGer/UnityToolchainsTrick/tree/main/Assets/Editor/Examples/Example_49_Friend"&gt;UnityToolchainsTrick&lt;/a&gt;中写的教程&lt;/p&gt;
&lt;p&gt;我也非常推荐&lt;code&gt;UnityToolchainsTrick&lt;/code&gt;库,很多大佬分享了不少编辑器方面的知识&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-C#"&gt;//Create: Icarus
//ヾ(•ω•`)o
//2022-03-14 01:31
//Unity.InternalAPIEngineBridge.024

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace CabinIcarus.EditorFrame.UnityBind
{
    public static class PrefabUtilityHelp
    {
        /// &amp;lt;summary&amp;gt;
        /// 创建预制体变体
        /// UnityCsReference\Editor\Mono\ProjectWindow\ProjectWindowUtil.cs
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name=&amp;quot;gameObjects&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
        public static GameObject[] CreatePrefabVariants(params GameObject[] gameObjects)
        {
            if (gameObjects == null)
                return null;

            foreach (var go in gameObjects)
            {
                if (go == null || !EditorUtility.IsPersistent(go))
                    return null;
            }

            var createdVariants = new List&amp;lt;GameObject&amp;gt;();
            foreach (var go in gameObjects)
            {
                string sourcePath  = AssetDatabase.GetAssetPath(go);
                string sourceDir   = Path.GetDirectoryName(sourcePath).Replace('\\', '/');
                string variantPath = GetPrefabVariantPath(sourceDir, go.name);
                variantPath = AssetDatabase.GenerateUniqueAssetPath(variantPath);
                
                var variant = PrefabUtilityHelp.CreateVariant(go, variantPath);

                if (variant != null)
                    createdVariants.Add(variant);
            }

            if (createdVariants.Count &amp;gt; 0)
            {
                Selection.objects = createdVariants.ToArray();
                ProjectWindowUtil.FrameObjectInProjectWindow(createdVariants.Last().GetInstanceID());
            }

            return createdVariants.ToArray();
        }
        
        static string GetPrefabVariantPath(string folder, string gameObjectName)
        {
            return string.Format(&amp;quot;{0}/{1} Variant.prefab&amp;quot;, folder, gameObjectName);
        }
        
        public static GameObject CreateVariant(GameObject assetRoot, string path)
        {
            return PrefabUtility.CreateVariant(assetRoot, path);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;晒一下目前工具的样子,哈哈&lt;/p&gt;
&lt;p&gt;&lt;img src="/Icarus/ServiceFiles//1/2022/3/1647194213189.png" alt="/Icarus/ServiceFiles//1/2022/3/1647194213189.png" /&gt;&lt;/p&gt;
&lt;p&gt;生成的结果&lt;/p&gt;
&lt;p&gt;&lt;img src="/Icarus/ServiceFiles//1/2022/3/1647194274395.png" alt="/Icarus/ServiceFiles//1/2022/3/1647194274395.png" /&gt;&lt;/p&gt;
</description>
      <pubDate>Sun, 13 Mar 2022 17:44:15 +0800</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="false">http://cabinicarus.com/posts/synty家的polygon模型-mixamo-动画处理</guid>
      <link>http://cabinicarus.com/posts/synty%E5%AE%B6%E7%9A%84polygon%E6%A8%A1%E5%9E%8B-mixamo-%E5%8A%A8%E7%94%BB%E5%A4%84%E7%90%86</link>
      <title>Synty家的POLYGON模型-Mixamo 动画处理</title>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=9H0aJhKSlEQ"&gt;官方的视频教程 Youtube&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Mixamo的操作:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;上传POLYGON模型&lt;/li&gt;
&lt;li&gt;选择动画,然后下载&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;处理脚本:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;//处理动画的3个Bake Into Pose
var path = AssetDatabase.GUIDToAssetPath(guid);
                
var importer = AssetImporter.GetAtPath(path);

if (importer is ModelImporter modelImporter)
{
    modelImporter.animationType = ModelImporterAnimationType.Human;
    ModelImporterClipAnimation[] clips = modelImporter.clipAnimations;

    if (clips.Length == 0)
    {
        clips = modelImporter.defaultClipAnimations;
    }

    foreach (var clipAnimation in clips)
    {
        clipAnimation.lockRootRotation   = true;
        clipAnimation.lockRootHeightY    = true;
        clipAnimation.lockRootPositionXZ = true;
    }

    modelImporter.clipAnimations = clips;
}

//修改骨骼源
var path     = AssetDatabase.GUIDToAssetPath(guid);
var importer = AssetImporter.GetAtPath(path);

if (importer is ModelImporter modelImporter)
{
    temp.Add(modelImporter);
    modelImporter.avatarSetup  = ModelImporterAvatarSetup.CopyFromOther;
    modelImporter.sourceAvatar = /*这里是在Mixamo中上传模型的Avatar,如果使用Create模式,那一些动画的会错误*/;
}
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Wed, 23 Feb 2022 19:57:26 +0800</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="false">http://cabinicarus.com/posts/unleash-部署</guid>
      <link>http://cabinicarus.com/posts/unleash-%E9%83%A8%E7%BD%B2</link>
      <title>Unleash 部署</title>
      <description>&lt;p&gt;&lt;a href="https://github.com/Unleash/unleash"&gt;&lt;code&gt;Unleash&lt;/code&gt;&lt;/a&gt;它的管理方式为:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;功能开关&lt;/li&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt;变量&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我本来想的是能直接在网页管理&lt;code&gt;变量&lt;/code&gt;就行,但是&lt;code&gt;Unleash&lt;/code&gt;是一个更好的. 在体验了官方的demo后,我就立马克隆下来部署本地测试了. 超出我预期了,初步体验下来,太符合自己的需求了.官方也提供了很多语言的SDK,不需要自己写了.&lt;/p&gt;
&lt;p&gt;这里就记录下部署方式,官方文档的部署也可以,不过我喜欢源码自己部署,官方文档的是下载他们的包进行部署,操作性相对低了.&lt;/p&gt;
&lt;p&gt;部署前准备:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;NodeJs &amp;gt;= 14,&lt;/li&gt;
&lt;li&gt;PostgreSQL &amp;gt;= 10&lt;/li&gt;
&lt;li&gt;ts-node (安装全局)&lt;/li&gt;
&lt;li&gt;yarn (安装全局)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="dev"&gt;Dev部署步骤:&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;克隆&lt;a href="https://github.com/Unleash/unleash"&gt;&lt;code&gt;Unleash&lt;/code&gt;&lt;/a&gt; &lt;code&gt;git clone https://github.com/Unleash/unleash.git&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;根目录运行&lt;code&gt;npm i&lt;/code&gt;(如果没有安装yarn,这里会报没有&lt;code&gt;yarn&lt;/code&gt;错)&lt;/li&gt;
&lt;li&gt;修改&lt;code&gt;src/server-dev.ts&lt;/code&gt;中的数据库配置项,需要先创建下数据库,然后配置下自己的数据库用户名和密码及地址/端口&lt;/li&gt;
&lt;li&gt;根目录运行&lt;code&gt;ts-node src/server-dev.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;然后你会看到控制台显示一个&lt;code&gt;Creating default user &amp;quot;admin&amp;quot; with password &amp;quot;unleash4all&lt;/code&gt;那就是成了&lt;/li&gt;
&lt;li&gt;然后打开就可以访问&lt;a href="http://localhost:4242/"&gt;localhost:4242&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="build"&gt;build发布运行&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;根目录运行&lt;code&gt;npm run build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;根目录运行&lt;code&gt;npm run start&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="devdevsrcserver.tsstartserver-dev"&gt;非dev部署(前几个步骤和Dev部署一样,就是在数据库等配置修改,是修改环境变量或者修改&lt;code&gt;src/server.ts文件的start方法参数,将server-dev的参数复制过来改改&lt;/code&gt;)我没测试过,不过大体读了下代码,做的总结:&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;在根目录创建一个&lt;code&gt;.env&lt;/code&gt;的文件,然后设置环境变量就行,数据库设置中提到过一些环境变量如:&lt;a href="https://docs.getunleash.io/deploy/configuring_unleash_v3"&gt;DATABASE_URL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;修改参数的方式&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class="language-ts"&gt; unleash.start({
      //数据库设置
      db:{

      },
      //服务器设置
      server:{
          port:1234//端口
          unleashUrl:process.env.UNLEASH_URL || 'http://localhost:4242'
      }
  });
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Fri, 28 Jan 2022 17:19:06 +0800</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="false">http://cabinicarus.com/posts/dota2-指定lua脚本的使用</guid>
      <link>http://cabinicarus.com/posts/dota2-%E6%8C%87%E5%AE%9Alua%E8%84%9A%E6%9C%AC%E7%9A%84%E4%BD%BF%E7%94%A8</link>
      <title>DOTA2 指定lua脚本的使用</title>
      <description>&lt;p&gt;当在KV或者场景中指定一个lua文件时,会执行该lua文件的&lt;code&gt;Precache/Spawn&lt;/code&gt;方法,以及会有一个&lt;code&gt;thisEntity&lt;/code&gt;成员可以使用,该成员是执行该脚本的entity,场景的话就是场景中的entity,&lt;/p&gt;
&lt;p&gt;一个例子&lt;code&gt;场景粒子播放&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function Spawn()
{
    // @ts-ignore
    const entity = thisEntity as CParticleSystem;

    FireEntityIOInputString(entity.GetEntityHandle(), &amp;quot;Start&amp;quot;,&amp;quot;&amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;
</description>
      <pubDate>Fri, 17 Dec 2021 16:40:14 +0800</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="false">http://cabinicarus.com/posts/游戏设计中一些关键词</guid>
      <link>http://cabinicarus.com/posts/%E6%B8%B8%E6%88%8F%E8%AE%BE%E8%AE%A1%E4%B8%AD%E4%B8%80%E4%BA%9B%E5%85%B3%E9%94%AE%E8%AF%8D</link>
      <title>游戏设计中一些关键词</title>
      <description>&lt;p&gt;&lt;a href="https://youtu.be/NpyfEsVzL4w?t=188"&gt;&lt;code&gt;Diegetic UI&lt;/code&gt;&lt;/a&gt; 是3DUI/世界ui&lt;/p&gt;
</description>
      <pubDate>Sun, 21 Nov 2021 09:48:53 +0800</pubDate>
    </item>
    <item>
      <guid
        isPermaLink="false">http://cabinicarus.com/posts/dota2-一些代码记录</guid>
      <link>http://cabinicarus.com/posts/dota2-%E4%B8%80%E4%BA%9B%E4%BB%A3%E7%A0%81%E8%AE%B0%E5%BD%95</link>
      <title>DOTA2 一些代码记录</title>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;GameUI.SetCameraYaw&lt;/code&gt; 相机的Y旋转&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;GameUI.SetCameraPitchMin/SetCameraPitchMax&lt;/code&gt; 相机的最小/最大俯仰角度&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description>
      <pubDate>Fri, 29 Oct 2021 17:10:58 +0800</pubDate>
    </item>
  </channel>
</rss>