【Unity2018】 ShaderGraphで遊ぼう!
Unity2018で、ついにShaderGraphが追加されました。 ↓のような感じで、ノードを繋げることでデザイナーでもシェーダーを簡単に開発することができる機能です。
元々Unreal Engine 4などのHD向けのゲームエンジンではあった機能で、これと同じような機能を持ったUnityAssetなども販売されていましたが、ついに公式でのサポートが入りました。
同じくUnity2018から正式版になったScriptableRenderPipelineという機能がありますが、プロジェクトで採用したRenderPipelineごとに大きくシェーダーコードが変わるため、アーティストのレイヤーではそこの差異を吸収したい!という目的もあり、優先的に実装されたっぽい雰囲気を感じています。
今回は、このShaderGraphを使い、適当なサイバーっぽいシェーダーを作ってみようと思います。
続きを読む【Unity】UGUIのRectTransformを100倍快適に扱うためのユーティリティを作った
概要
この記事はCluster,Inc. Advent Calendar 2017の14日目の記事です。
こんな感じのWindowのようなものを作っていたのですが、 RectTransformの具体的なサイズが知りたい!
親Transformの左端、右端から、相対的に位置を指定したい!
など、RectTransformに思うところが多かったので、RectTransformを便利に扱うためのユーティリティを作ってみました。
コード
/** MIT Lisence Copyright (c) 2017 Cluster,Inc. This software is released under the MIT License. http://opensource.org/licenses/mit-license.php */ public enum Corner { LeftTop, RightTop, LeftBottom, RightBottom, }
/** MIT Lisence Copyright (c) 2017 Cluster,Inc. This software is released under the MIT License. http://opensource.org/licenses/mit-license.php */ using System; using System.Linq; using UnityEngine; public static class RectTransformUtil { public static Bounds GetWorldBounds(this RectTransform rectTransform) { var corners = new Vector3[4]; rectTransform.GetWorldCorners(corners); var center = corners.Aggregate(Vector3.zero, (current, corner) => current + corner) / corners.Length; var size = new Vector3( corners.Max(corner => corner.x) - corners.Min(corner => corner.x), corners.Max(corner => corner.y) - corners.Min(corner => corner.y), 1); return new Bounds(center, size); } public static Vector2 GetRelativePosition(this RectTransform rectTransform, Corner corner) { var parentBounds = rectTransform.parent.GetComponent<RectTransform>().GetWorldBounds(); var bounds = rectTransform.GetWorldBounds(); var pos = Vector2.zero; switch (corner) { case Corner.LeftBottom: case Corner.RightBottom: pos.y = bounds.min.y - parentBounds.min.y; break; case Corner.LeftTop: case Corner.RightTop: pos.y = parentBounds.max.y - bounds.max.y; break; default: throw new ArgumentOutOfRangeException("corner", corner, null); } switch (corner) { case Corner.LeftTop: case Corner.LeftBottom: pos.x = bounds.min.x - parentBounds.min.x; break; case Corner.RightTop: case Corner.RightBottom: pos.x = parentBounds.max.x - bounds.max.x; break; default: throw new ArgumentOutOfRangeException("corner", corner, null); } return pos; } public static void SetRelativePosition(this RectTransform rectTransform, Vector2 pos, Corner corner) { var parentBounds = rectTransform.parent.GetComponent<RectTransform>().GetWorldBounds(); var bounds = rectTransform.GetWorldBounds(); var anchoredPosition = rectTransform.position; switch (corner) { case Corner.LeftBottom: case Corner.RightBottom: anchoredPosition.y += parentBounds.min.y - bounds.min.y + pos.y; break; case Corner.LeftTop: case Corner.RightTop: anchoredPosition.y += parentBounds.max.y - bounds.max.y - pos.y; break; default: throw new ArgumentOutOfRangeException("corner", corner, null); } switch (corner) { case Corner.LeftTop: case Corner.LeftBottom: anchoredPosition.x += parentBounds.min.x - bounds.min.x + pos.x; break; case Corner.RightTop: case Corner.RightBottom: anchoredPosition.x += parentBounds.max.x - bounds.max.x - pos.x; break; default: throw new ArgumentOutOfRangeException("corner", corner, null); } rectTransform.position = anchoredPosition; } }
つかいかた
rectTransform.GetWorldBounds()
のように、拡張メソッドとして使えるようになっています。
GetWorldBounds
Boundsとして、ワールド空間でのRectTransformの位置やサイズ、各点の位置などが取得できます。
GetRelativePosition / SetRelativePosition
右側/左側/上側/下側が、親の端からどのくらい離れているかを相対位置で取得/設定できます。 親のオブジェクトをはみ出さないように位置を制限する、といった挙動の実装に便利です。
微妙なところ
パフォーマンス
メソッドが呼ばれるたびにGetComponent<RectTransform>()
を2回も呼んでいるので、それなりにパフォーマンスが悪いです。
適宜、必要に応じてキャッシュする仕組みなどを作ると良いと思います。
親がRectTransformじゃない場合の挙動は?
わからん 😱
親にスケールがかかっていた場合の挙動は?
わからん😇😇😇 なんかもっといいアプローチがあったら教えてください
SurfaceShaderで主線を描画する
概要
主線を表示し、エッジを強調するシェーダーをSurface Shaderで作りました。
主線に影は乗っていませんが、ライトの色を変更すると主線の色も変わるのがキモです。
仕組み
1パス目
普通にモデルを描画しています
2パス目
頂点シェーダーで少しだけ法線方向に拡大したものを描画します。 自前のライティング関数を指定することで、影を描画しないように変更しています。
コード
/* StandardEdge Copyright(c) 2017 Yutaka Sato This software is released under the MIT License. http://opensource.org/licenses/mit-license.php */ Shader "Custom/StandardEdge" { Properties { _Color("Color", Color) = (1,1,1,1) _EdgeColor("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 _EdgeWidth("EdgeWidth", Range(0, 0.1)) = 0.02 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGINCLUDE #include "UnityPBSLighting.cginc" half _Glossiness; half _Metallic; float4 _Color; float3 _EdgeColor; float _EdgeWidth; sampler2D _MainTex; struct Input { float2 uv_MainTex; }; void surf(Input IN, inout SurfaceOutputStandard o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } void edgeVert(inout appdata_full v) { v.vertex.xyz += v.normal * _EdgeWidth; } void edgeSurf(Input IN, inout SurfaceOutputStandard o) { o.Albedo = _EdgeColor; } half4 LightingEdge(SurfaceOutputStandard s, half3 lightDir, half atten) { half4 c; c.rgb = s.Albedo * _LightColor0.rgb; c.a = s.Alpha; return c; } ENDCG Cull Back CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 ENDCG Cull Front CGPROGRAM #pragma surface edgeSurf Edge fullforwardshadows vertex:edgeVert #pragma target 3.0 ENDCG } FallBack "Diffuse" }
【Unity】"Error building Player because scripts had compiler errors"とだけ出た時のエラー箇所の探し方
Editorビルドのみが失敗しているときなど、極稀にError building Player because scripts had compiler errors
とだけログに出力されることがあります。
それしかエラーが出ないため該当箇所の特定が難しかったのですが、対処方法がわかったためメモっておきます。
続きを読む