unityでよく使うC#のクラス、メソッド、などの話
はじめまして、学部一年の渡辺です。 初めてのブログということで、自分のような初心者の方に役立ちそうなテーマについて書こうと思います。 と、言ってもまだunityを触り始めて半年弱(モデリングにも挑戦したりしていたので実質3か月くらい)なので、間違いがあるかもしれません。その場合、指摘してくださるとうれしいです。(のちのち画像等追加します)
よく使うもの
はじめに
私は大学でC、サークルでC#を同時にやったため、オブジェクト指向型についての理解をちゃんとせずに勉強してしまったため、かなり学ぶ上で混乱が生じました。 そのためまずオブジェクト指向型の理解をすべきだと思います。
クラス
Input
まずゲームといえばプレイヤーをコントロールしなければなりません。 コントローラーなりキーボードなりの入力を受け付ける。
メソッド | 説明 |
---|---|
Input.GetKey | 押している間 |
Input.GetKeyDown | 押した瞬間 |
Input.GetKeyUp | 離した瞬間 |
Input.GetMouseButton(0) | 左ボタン |
Input.GetMouseButton(1) | 右ボタン |
Input.GetMouseButton(2) | 中ボタン |
使用例
if (Input.GetKey(KeyCode.W))
Input.GetAxis() float型で返す
使用例
void Update() { float h = horizontalSpeed * Input.GetAxis("Mouse X"); float v = verticalSpeed * Input.GetAxis("Mouse Y"); transform.Rotate(v, h, 0); }
Edit -> Project Settings -> InputでInputManagerが見れます。
GameObject
ゲーム内のオブジェクトを扱うクラス
変数 | 説明 |
---|---|
transform | ゲームオブジェクトの位置 |
layer | ゲームオブジェクトのレイヤー |
tag | ゲームオブジェクトのタグ |
name | 名前 |
Transform
オブジェクトの位置、回転、スケールを扱うクラス
変数 | 説明 |
---|---|
position | ワールド座標における位置(Vector3) |
rotation | ワールド座標における方向(Quaternion) |
localScale | 大きさ |
forward | 物体が向いている方向 |
transform.LookAt(target((Transform target)));
targetに向かせる
SceneManager
シーンの切り替え等に利用できます。 タイトル画面やリザルト画面を作るときに必要になるかと。
使用する際は
using UnityEngine.SceneManagement
と宣言する必要があります。またFile->BuildSettingsでシーンの登録をする必要があります。
使用例
SceneManager.LoadScene("シーン名");
Rayの使い方
Rayは光線という意味ですが、unityでもよく使います。 ある点から光線を出し、当たったオブジェクトの情報を取得できます。 いろいろとややこしいですが、覚えるとかなり便利かと思います。
Ray
Rayの宣言
Ray(origin(原点), direction(方向))
使用例
Ray ray = new Ray(transform.position, transform.forward);
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit
Rayの当たったものの情報を得る。
変数 | 説明 |
---|---|
transform | 衝突したコライダーまたは Rigidbody の Transform |
collider | ヒットしたコライダー |
distance | レイの原点から衝突点までの距離 |
Physics.Raycast
Physics.Raycastには二つ方法があります。
- Physics.Raycast(原点, 方向, out hit*1, Rayの長さ, 当たるレイヤー);
- Physics.Raycast(ray*2, out hit, Rayの長さ, 当たるレイヤー);
Rayの長さは指定しない場合無限になります。 レイヤーは指定しない場合すべてのレイヤーが対象です。
当たり判定
OnCollisionEnter関数
衝突したかどうかを判断する関数です。
void OnCollisionEnter(Collision 当たった物体) { Debug.Log(当たった物体.gameObject.name); }
OnTriggerEnter関数
物体のColliderのIsTriggerにチェックを入れた場合、衝突しなくなりすり抜けます。 その場合の当たり判定はOnTriggerEnter関数を使います。
void OnTriggerEnter(Collider 入った物体) { Debug.Log(入った物体.gameObject.name); }
最後に
今までコピペしてそれっぽいスクリプトを書いていましたが、今後は自力で書けるようになりたいと思い、この記事を書かせていただきました(というかほぼメモ)。同じような方のお力になれていたら幸いです。 学んだことがあったらこれからも追加していきたいと思います。
参考にさせていただいたサイト
開発者視点のVR酔い対策
学部2年の星野です。自分が大体のもので酔いやすいこともあり、VRコンテンツを制作する際にVR酔いについてはかなり注意しているつもりです。今回は開発者視点におけるVR酔いの対策について書いていきたいと思います。
VR酔いとは
VRを体験している途中や後で、吐き気や頭痛などの症状がでること。
症状としてはほぼ車酔いと同じ
原因としてはいくつか説があるが、視覚と感覚のずれによるものという説が有力(車酔いと同じ)
自分自身も何回かなったことがありますが、その時はかなりキツかったです。(もちろん状況や人によって症状は変わります。)
VR酔いの対策
fpsとリフレッシュシートを確保する
fpsはアプリ側、リフレッシュシートはヘッドセット側の映像更新の頻度を表す
ちゃんと確保しないと映像が遅延するため酔いやすくなる
ときには解析度を犠牲にしてでもfpsを確保
VRを違和感なく進行するためには90fps以上必要
次の動きを予想させる
- 視点や画面が大きく切り替わる前に予告を出したりフェードインやフェードアウトを使うことで、脳に準備をさせる
移動の実装には注意する
テレポート
コックピットなどの表示(周辺視野を隠す)
移動させない(ルームスケールの範囲内)
実践
自分の参加しているチーム開発のカメラや移動のシステムを担当しました。 下の動画は現在の進捗です。
次の動きを予想させる→フェードイン、アウトを使う。 移動の実装→テレポート
そのおかげか、気持ち悪さや酔いを感じたことはなかったです。(慣れもあるかもしれません)
まとめ
今後もVRコンテンツを制作する時には上であげたことに注意していきたいと思います。
【Odin Inspector】NPCの振る舞いをインスペクターで設定する
はじめに
こんにちは、学部3年の木村です。
タイトルの通り、ゲームに登場するNPCの行動をインスペクターで設定できるようにします。
想定するゲームにはNPCとしてMonster(獅子舞や仏像)が存在し、 各NPCは現在の状態に応じて探索や追跡などの行動をとることができます。
この場合、Dictionary
を使って状態と行動を対応付けたいのですがUnityのInspectorではGenericsを扱えないため、アクセス修飾子をpublic
にしたり属性にSerializeFieled
を付けたりしてもInspectorには表示されません。抽象クラスやインターフェースも同様です。
そこで、Odin - Inspector and Serializerというアセットを使用しました。
Odinとは
OdinはUnityのInspectorを使いやすくするプラグインです。
導入するだけでList等の表示がいい感じになったり、 (多分)何でもシリアライズできるようになったり、便利な属性が80以上使えるようになります。odininspector.comではどんなことができるようになるかがアニメーション付きで紹介されています。
$55の有料アセットですが、ゲーム制作中のパラメータ調整などが圧倒的に快適になるとても便利なアセットです。
本編
一部省略していますが、 大体以下のような構成です。
Monster
が継承しているSerializedMonoBehaviour
は、Dictionary
等もシリアライズできる(Inspectorで設定できる)MonoBehaviour
です。元のMonoBehaviour
の機能はそのまま使えます。
Inspectorでは次のように表示されます。(クラス図ではMonster
に定義しているActionsTable
がMonsterActionRepository
で定義されています。)
Dictionary
がInspectorに表示されており、Keyに状態(MonsterState
)、Valueにその状態のときにとる行動(抽象クラスNpcAction
の実装)を指定することでNPCの振る舞いを設定できます。
ついでに
OdinのButton
属性を使って、InspectorのボタンからMonsterの状態を変更できるようにしています。
public bool _enableDebug; [Button, ShowIf(nameof(_enableDebug)), EnableIf(nameof(_enableDebug))] private void ChangeState(MonsterState state) { // 状態をstateに変更 }
終わり
Odinの紹介と活用例でした。
ゲーム制作中にUnityのインスペクターを使っていると微妙に手の届かないかゆいところがあり、自分でエディタ拡張を書いていたら沼にハマり肝心のゲーム制作が進まないということがあるかもしれません。そんなときにOdinはかゆいところをいい感じにかいてくれます。
ちょっと高めのアセットですがUnityがとても快適になるので、よかったら導入してみてはいかがでしょうか。
三次元極座標系でパーティクル
学部4年のユムルです。
最近Shaderをかいたり、VRのMV (Music Video) を作ったりして遊んでます。
作った物をVRSNSのVRChatにて人に見せたりして楽しんでいるのですが、最近ブタジエン(https://twitter.com/butadiene121)さんのシェーダーパーティクルに魅せられて、真似して次のようなシェーダーパーティクルを作りました。
綺麗なパーティクルできたー!
— ユムル (@Yumuru_n) 2020年9月7日
お花くるくるー
(2週間前に作った) pic.twitter.com/IwA7mcsO9I
これの解説をします。
パーティクルとして使うメッシュと表現の決定
今回はCubeのメッシュをもとに、次の表現を使うことにします。
書いたShaderは次のものです。
Shader "PolarParticle/Cube1" { Properties { } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent" } // 透明 Cull off Blend SrcAlpha One ZWrite Off LOD 100 Pass { CGPROGRAM #pragma target 5.0 #pragma vertex VS #pragma fragment FS #include "UnityCG.cginc" struct VS_OUT { float4 vertex : SV_Position; float4 texcoord : TEXCOORD0; float4 color : COLOR; }; VS_OUT VS(appdata_full v) { VS_OUT o; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = v.texcoord; o.color = float4(0, 1, 1, 1); return o; } float4 FS(VS_OUT i) : SV_Target { float2 uv = i.texcoord.xy; float2 p = uv * 2.0 - 1.0; float t = 0.01 / min(abs(abs(p.x) - 1.0), abs(abs(p.y) - 1.0)); t = saturate(t); return float4(i.color.xyz, t); } ENDCG } } }
メッシュの大量複製
メッシュをパーティクルとして扱うために、メッシュを大量にコピーしたいです。
私はこれをするために2種類の方法を知っています。 普通は次の方法1を使えば良いと思いますが、VRChatではそれをすることはできないので方法2を使いました。
それぞれの方法で試しに100万個のCubeを表示してみますが、後につくる極座標のパーティクルは1024個で作成します。
方法1
次の記事を参考にします。 shitakami.hatenablog.com feelingames.hatenablog.com
次のコードを書きます。
using UnityEngine; public class GPUInstance : MonoBehaviour { public Mesh mesh; public Material material; public Bounds bounds; public int instanceNum; public ComputeBuffer buffer; void Start() { var args = new uint[5] { 0, 0, 0, 0, 0 }; args[0] = mesh != null ? (uint) mesh.GetIndexCount(0) : 0; args[1] = (uint) instanceNum; buffer = new ComputeBuffer(1, args.Length * sizeof(uint), ComputeBufferType.IndirectArguments); buffer.SetData(args); } void Update() { Graphics.DrawMeshInstancedIndirect( mesh, 0, material, bounds, buffer); } void OnDestroy() { if (buffer != null) buffer.Release(); } }
取り敢えず大量のCubeを規則正しく並べるシェーダーを書きます、
Shader "PolarParticle/ManyCube" { Properties { } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent" } Cull off Blend SrcAlpha One ZWrite Off LOD 100 Pass { CGPROGRAM #pragma target 5.0 #pragma vertex VS #pragma fragment FS #include "UnityCG.cginc" struct VS_OUT { float4 vertex : SV_Position; float4 texcoord : TEXCOORD0; float4 color : COLOR; }; static uint particleNum = 1000000; // パーティクルの数 VS_OUT VS(appdata_base v, uint instanceId : SV_InstanceID) { VS_OUT o; uint id = instanceId; // パーティクルのID uint n = pow(particleNum, 1.0 / 3.0); float particleSize = 0.1; // パーティクルのサイズ float interval = 1; // パーティクル間の距離 float zoneLength = (n-1) * interval; // 全体の範囲の長さ uint3 axisId = uint3( // 極ごとのID id % n, id / n % n, id / (n * n)); float3 pos = (float3)(-zoneLength / 2) + axisId * interval; v.vertex.xyz = v.vertex.xyz * particleSize + pos; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = v.texcoord; o.color = float4(0, 1, 1, 1); return o; } float4 FS(VS_OUT i) : SV_Target { float2 uv = i.texcoord.xy; float2 p = uv * 2.0 - 1.0; float a = 0.01 / min(abs(abs(p.x) - 1.0), abs(abs(p.y) - 1.0)); a = saturate(a); return float4(i.color.rgb, a); } ENDCG } } }
書いたシェーダからマテリアルを作成し、GameObjectに先ほどのC#のコードをアタッチして、次のように100万個のCubeが出るように設定します。
シーンを再生すると、100万個のCubeの位置が頂点シェーダーによって決められているのを確認できます。
後のパーティクルの為、今回はInstance Numを1024に設定してください。
方法2
VRChatでメッシュのパーティクルを使う場合は、C#によるスクリプトを組み込んだ作品をアップロードできません。したがって、方法1も使えません。 代わりに間接的にC#を用いて、Meshを複製してアセットファイル化するスクリプトを書き、更にジオメトリシェーダーの[instance(31)]にて31倍にメッシュを増やします。
メッシュを複製したアセットファイルを作成するため、C#のエディタ拡張を書きます
using System.Linq; using System.Collections; using System.Collections.Generic; using UnityEngine; #if UNITY_EDITOR using UnityEditor; public class MeshCopy : EditorWindow { [MenuItem("MyEditor/MeshCopy")] static void Open() { GetWindow<MeshCopy>("MeshCopy"); } Mesh useMesh; // コピー元のメッシュ int copyN; // 複製する数 void OnGUI() { useMesh = (Mesh) EditorGUILayout.ObjectField("Use Mesh", useMesh, typeof(Mesh), false); copyN = EditorGUILayout.IntField("Copy Num", copyN); if (GUILayout.Button("Mesh N Copy")) { MeshNCopy(); } } void MeshNCopy() { var vertices = new List<Vector3>(); var texcoord = new List<Vector3>(); var triangles = new List<int>(); var normals = new List<Vector3>(); var tangents = new List<Vector4>(); var colors = new List<Color>(); // ここのループでメッシュをコピー、texcoordのz値にidを入れておく for (int i = 0; i < copyN; i++) { vertices.AddRange(useMesh.vertices); texcoord.AddRange(useMesh.uv.Select(v => new Vector3(v.x, v.y, i))); triangles.AddRange(useMesh.triangles .Select(index => index + i * useMesh.vertexCount)); normals.AddRange(useMesh.normals); tangents.AddRange(useMesh.tangents); colors.AddRange(useMesh.colors); } var mesh = new Mesh(); mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; // indexFormatを変えておかないとtrianglesの値の上限を余裕で超えてしまう mesh.SetUVs(0, texcoord); mesh.triangles = triangles.ToArray(); mesh.normals = normals.ToArray(); mesh.tangents = tangents.ToArray(); mesh.colors = colors.ToArray(); string path = string.Format("Assets/{0}x{1}.asset", useMesh.name, copyN); AssetDatabase.CreateAsset(mesh, path); AssetDatabase.SaveAssets(); } } #endif
Unity上部のメニューにある、MyEditor -> MeshCopyを開き、Cubeのメッシュを設定し、後でメッシュを更に31倍するので、Copy Numを100万 / 31 = 約33000個 に設定しボタンを押します。
すると、Assets直下に33000個のCubeメッシュのアセットファイルが生成されます。
とはいえこの時点で、メッシュファイルのサイズは81MBになってしまうので、実用的に考えるならCube1024個で2MBくらいのものになるでしょう。
Shaderの方は次のようです。こちらもcubeを規則正しく並べておきます。 メッシュのサイズを抑え、ジオメトリシェーダのinstanceにて更に31倍までポリゴンを増やすことができます。 頂点シェーダーVSは値をそのまま返すのみにし、ジオメトリシェーダGSにて頂点位置を決定します。
Shader "PolarParticle/ManyCube2" { Properties { } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent" } Cull off Blend SrcAlpha One ZWrite Off LOD 100 Pass { CGPROGRAM #pragma target 5.0 #pragma vertex VS #pragma geometry GS #pragma fragment FS #include "UnityCG.cginc" struct GS_OUT { float4 vertex : SV_Position; float4 texcoord : TEXCOORD0; float4 color : COLOR; }; appdata_base VS(appdata_base v) { return v; } #define instanceN 31 [instance(instanceN)] [maxvertexcount(3)] void GS(triangle appdata_base i[3], inout TriangleStream<GS_OUT> stream, uint gsid : SV_GSInstanceID) { for (int j = 0; j < 3; j++) { appdata_base v = i[j]; GS_OUT o; uint id = gsid + instanceN * v.texcoord.z; // パーティクルのIDを計算 uint n = pow(33000 * instanceN, 1.0/3.0); float particleSize = 0.1; float interval = 1; float zoneLength = (n-1) * interval; uint3 axisId = uint3( id % n, id / n % n, id / (n * n)); float3 pos = (float3)(-zoneLength / 2) + axisId * interval; v.vertex.xyz = v.vertex.xyz * particleSize + pos; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = v.texcoord; o.color = float4(0, 1, 1, 1); stream.Append(o); } stream.RestartStrip(); } float4 FS(GS_OUT i) : SV_Target { float2 uv = i.texcoord.xy; float2 p = uv * 2.0 - 1.0; float a = 0.01 / min(abs(abs(p.x) - 1.0), abs(abs(p.y) - 1.0)); a = saturate(a); return float4(i.color.rgb, a); } ENDCG } } }
SkinnedMeshRendererにてBoundsを設定しつつ使います。
方法1との違いは、頂点シェーダーでなくジオメトリシェーダを使うこと、idの設定に一手間加えることです。
以降のシェーダーのコードは方法1を使う場合のコードとします。もし、VRChatのために方法2を使う人は読み変えてください。
後のパーティクルの為、今回は1024個のパーティクルを表示する為に1024/16 = 64個のCubeメッシュを生成し、後でジオメトリのinstanceにて16倍するように設定してください。
極座標系によるパーティクルの位置決定
x座標、y座標をもとに、座標を決定する座標系を直交座標と言いますが、
極座標系という座標系も存在します。
極座標系は原点からの距離rと、x軸から反時計回りへの角度θによる(r, θ)で座標を決定します。
原点からのrをsinやcosなどの三角関数と共に角度によって適当に決めるようにすると、綺麗な模様が描けます
二次元の極座標系(r, θ)を直交座標系(x, y)に変換する式は次の通りです
x = r cosθ
y = r sinθ
今回のパーティクルではこれを三次元で考えます。
三次元極座標は、原点からの距離r、角度はz軸からの角度θとx軸からの角度φによる(r, θ, Φ)によって決まるようです。 今回はUnityのシェーダーで実装しますから、数学でz軸であるところはy軸、y軸のところがz軸であると考えます。 したがって、原点からの距離r、y軸からの角度θ, x軸からの角度Φで考え、 三次元直交座標系(x, y, z)への変換は次のようです。
x = r sinθ cosφ
y = r cosθ
z = r sinθ sinφ
ではシェーダを書いていきます。
パーティクルのidをもとに、パーティクルの位置を極座標系を用いて算出する関数を用意します。
最初に極座標系(r, θ, Φ)の変数と直交座標系への変換のコードを書いておきます。
#define PI UNITY_PI void particleTransform(uint id, out float3 pos) { float r = 1; float theta = 0; float phi = 0; pos = float3( r * sin(theta) * cos(phi), r * cos(theta), r * sin(theta) * sin(phi)); }
さて、二次元極座標において適当なグラフを示したときはr をθをもとに決定していましたが、
今回はidの値が元になります。
したがって、idの値を適当に変数 tに入れて扱うことにします。 `` float t = id * 0.01;
θをπ / 2にしておくと、phiの値によりxz座標上の値になります
float t = id * 0.01; float r = 1; float theta = PI / 2; float phi = t;
また、作成した関数を頂点シェーダに適応します。
VS_OUT VS(appdata_base v, uint instanceId : SV_InstanceID) { VS_OUT o; uint id = instanceId; float particleSize = 0.05; float3 pos; particleTransform(id, pos); v.vertex.xyz = v.vertex.xyz * particleSize + pos; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = v.texcoord; o.color = float4(0, 1, 1, 1); return o; }
θの値を適当なサイン波にしてみます。
float theta = PI / 2 + sin(5.5 * t) * 0.2;
Φの値も適当なサイン波にしてみます。
float phi = sin(t) * 3 * PI;
θのサイン波の大きさを敢えて小さくしていましたが、試しに大きくしてみます。
float theta = PI / 2 + sin(5.5 * t) * 0.7;
止まっていてもつまらないので、時間によって変化するようにします。
Φの値を時間によって変化させてみます。
float phi = sin(t) * 3 * PI + sin(t + _Time.y * 0.3) * 3;
なかなかかっこよくなってきました。
tの値、rの値も時間によって変化させてみます。
float t = id * 0.01 + _Time.y * 0.1;
float r = 0.2 + sin(3 * t);
パーティクルが全て同じ方向を向いているので、回転の設定をします。
この記事を参考に、回転の関数を書きます。行列のままの方が扱いやすいので行列のまま値の受け渡しを行います。
float3x3 rotate(float angle, float3 axis) { float3 a = normalize(axis); float s = sin(angle); float c = cos(angle); float r = 1.0 - c; return float3x3( a.x * a.x * r + c, a.y * a.x * r + a.z * s, a.z * a.x * r - a.y * s, a.x * a.y * r - a.z * s, a.y * a.y * r + c, a.z * a.y * r + a.x * s, a.x * a.z * r + a.y * s, a.y * a.z * r - a.x * s, a.z * a.z * r + c); }
また、サイズと色の設定も適当に設定します。
#define PI UNITY_PI void particleTransform(uint id, out float3 pos, out float3x3 rot, out float size, out float3 color) { // out 変数追加 float t = id * 0.01 + _Time.y * 0.1;; float r = 0.2 + sin(3 * t); float theta = PI / 2 + sin(5.5 * t) * 0.7; float phi = sin(t) * 3 * PI + sin(t + _Time.y * 0.3) * 3; pos = float3( r * sin(theta) * cos(phi), r * cos(theta), r * sin(theta) * sin(phi)); // rot, size, color設定 rot = mul(rotate(theta, float3(1, 0, 0)), rotate(phi - _Time.y * 3, float3(0, 1, 0))); size = cos(5.3 * t + _Time.y * 3.0) * 0.05; color = float3(sin(2.4 + t + _Time.y * 0.6), sin(0.7 + 2 * t - _Time.y * 0.6), sin(3.0 * t + _Time.y * 0.7)) / 2 + 0.5; }
頂点シェーダも書き変えます。
VS_OUT VS(appdata_base v, uint instanceId : SV_InstanceID) { VS_OUT o; uint id = instanceId; float particleSize = 0.05; float3 pos; float3x3 rot; float size; float3 color; particleTransform(id, pos, rot, size, color); v.vertex.xyz = mul(rot, v.vertex.xyz * size) + pos; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = v.texcoord; o.color = float4(color, 1); return o; }
かっこいいのができあがりました。
コードの全体は次のようです。
Shader "PolarParticle/Test" { Properties { } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent" } Cull off Blend SrcAlpha One ZWrite Off LOD 100 Pass { CGPROGRAM #pragma target 5.0 #pragma vertex VS #pragma fragment FS #include "UnityCG.cginc" struct VS_OUT { float4 vertex : SV_Position; float4 texcoord : TEXCOORD0; float4 color : COLOR; }; float3x3 rotate(float angle, float3 axis) { float3 a = normalize(axis); float s = sin(angle); float c = cos(angle); float r = 1.0 - c; return float3x3( a.x * a.x * r + c, a.y * a.x * r + a.z * s, a.z * a.x * r - a.y * s, a.x * a.y * r - a.z * s, a.y * a.y * r + c, a.z * a.y * r + a.x * s, a.x * a.z * r + a.y * s, a.y * a.z * r - a.x * s, a.z * a.z * r + c); } #define PI UNITY_PI void particleTransform(uint id, out float3 pos, out float3x3 rot, out float size, out float3 color) { float t = id * 0.01 + _Time.y * 0.1;; float r = 0.2 + sin(3 * t); float theta = PI / 2 + sin(5.5 * t) * 0.7; float phi = sin(t) * 3 * PI + sin(t + _Time.y * 0.3) * 3; pos = float3( r * sin(theta) * cos(phi), r * cos(theta), r * sin(theta) * sin(phi)); rot = mul(rotate(theta, float3(1, 0, 0)), rotate(phi - _Time.y * 3, float3(0, 1, 0))); size = cos(5.3 * t + _Time.y * 3.0) * 0.05; color = float3(sin(2.4 + t + _Time.y * 0.6), sin(0.7 + 2 * t - _Time.y * 0.6), sin(3.0 * t + _Time.y * 0.7)) / 2 + 0.5; } VS_OUT VS(appdata_base v, uint instanceId : SV_InstanceID) { VS_OUT o; uint id = instanceId; float particleSize = 0.05; float3 pos; float3x3 rot; float size; float3 color; particleTransform(id, pos, rot, size, color); v.vertex.xyz = mul(rot, v.vertex.xyz * size) + pos; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = v.texcoord; o.color = float4(color, 1); return o; } float4 FS(VS_OUT i) : SV_Target { float2 uv = i.texcoord.xy; float2 p = uv * 2.0 - 1.0; float a = 0.01 / min(abs(abs(p.x) - 1.0), abs(abs(p.y) - 1.0)); a = saturate(a); return float4(i.color.rgb, a); } ENDCG } } }
A-PxLが誕生してから、今まで。
こんにちは、ぶろっくのいずです。
初代部長である秋山さん達がこの部を作ってくださった時から3年以上が経ちました。 A-PxLの成り立ちを知る人もいなくなってきた事もあり、今までの活動をまとめました。 (※この記事について修正、追記出来る部員の方がいましたら気軽に変更をお願いします)
目次
A-PxL(旧 会津大学VR部)のこれまでの活動
2016年度
会津大VR部(会津大学) - Japan-VR-circles
3月5日:はてなブログ開設
2017年度
4月6日:会津大学内にカヤックVR分室を設立しました! | 面白法人カヤック
4月28日:Twitter開設
9月29日〜10月1日:VR部 開発合宿
10月7日〜10月8日:蒼翔祭(学祭)
12月:初代部長秋山さんが株式会社AnostVRを設立
2018年度
4月10日:新入生説明会
4月17日:今年の方針の説明 VR概論1
4月24日:VR概論2
5月8日:ゲームサウンドワークショップ
5月15日:3Dモデルワークショップ
5月22日:Git勉強会1
5月29日:Git勉強会2
6月30日:ブレスト研修会
7月3日:チーム進捗報告及びチーム活動
8月11日:オープンキャンパス
9月14日〜9月16日:開発合宿(南会津の宿泊施設CloudCamp)
10月6日〜10月7日:蒼翔祭(学祭)
10月16日:チーム進捗報告及びチーム活動
11月4日:デジゲー博2018(秋葉原UDX)
11月16日:IVRC決勝大会ユース部門銀賞を獲得
youtu.beご報告が遅くなりましたが、私たち会津大学VR部のチームFireFloworksが先日行われましたIVRC決勝大会にてユース部門銀賞を獲得することが出来ました!
— A-PxL (@aizu_PxL) 2018年11月17日
応援してくださった皆様、審査して頂いた審査員の皆様、その他多くの皆様本当にありがとうございました! https://t.co/rvEH7jDrMo
11月18日:パソコン甲子園にてゲームの展示
12月1日〜12月22日:健康づくりハッカソン
12月:部内面談
1月:部内面談
2月:次年度の役員決め
2月16日〜2月17日:新潟・山形・会津大学共同ハッカソンに参加naoto80840.github.io
2019年度
4月:役員の分担(代表者の他に副代表者、会計、自治会担当者を増員)
4月5日:部名を「Aizu-Progressive xr Lab(略称:A-PxL)」に変更
5月18日〜5月19日:VRキャラバン活動
6月16日:Oculus Quest体験会
この広い空間で近未来の機器を付けて謎の動きをする集団#A_PxL#OculusQuest体験会 pic.twitter.com/IYv9OoZzQs
— グッチー (@guchimoriVR82) 2019年6月16日
7月13日〜7月14日:新入生対抗ハッカソン
8月23日〜9月14日:学祭に向けてのPR動画制作
10月12日〜10月13日:蒼翔祭(学祭)は台風により中止
12月:部内VRコンテンツ体験会
1月31日:来年度の活動についてミーティング
2月14日:勉強会についての会議
3月1日:追いコン
2020年度
4月6日:部室があるAiCTを3Dスキャン
4月15日:clusterにてA-PxL新入生向けの説明会
4月29日〜5月10日:バーチャルマーケット4に出展
5月14日〜6月11日毎週木曜日:新入生向けのプログラミング勉強会
5月15日〜6月12日毎週金曜日:新入生向けのUnity勉強会
5月16日〜5月30日毎週土曜日:新入生向けのBlender勉強会
6月6日〜6月13日毎週土曜日:新入生向けのVFX勉強会
6月17日:OpenAppLab "2020"
7月11日:Git勉強会1
7月14日:部内でVR体験会
7月16日:Git勉強会2
7月17日:Git勉強会3
7月21日:チーム決め
9月:夏休み
10月10日:オンラインの蒼翔祭(学祭)
活動内容の変化
2016年度:?
2017年度:?
2018年度:チームに別れてゲームを制作。
2019年度:ゲーム部と新規開発部(NDD)に別れて活動。ゲーム部は毎週火曜日19:00〜21:00に中講義室M5にて定例会。新規開発部は毎週金曜日19:00〜21:00に研究棟北ラウンジにて定例会。
2020年度:ゲーム部と新規開発部を統合。毎週火曜日19:00からUBICの3Dシアターにて定例会(大学のテスト期間や大型の休みを除く)。周一でチームごとに進捗を報告しゲームを制作。
部員数の推移
(最大アクティブ数はSlackのアナリティクスより集計)
2016年度:総数11人→13人
2017年度:総数33人、最大アクティブ数33人、新部員20?人
2018年度:総数49?人、最大アクティブ数44人、新部員16人
2019年度:総数63?人、最大アクティブ数43人、新部員6人
2020年度:総数77人、最大アクティブ数38人、新部員6人
役員の推移
顧問:マイケル・コーエン先生
2017年度
代表者:Achu→Achu (@Achu_retro) | Twitter
2018年度
代表者:ゆべねこ→ゆべねこ (@yubeshineko) | Twitter
2019年度
代表者(新規開発部リーダー):Bigdra→bigdra (@bigdra50) | Twitter
副代表者(ゲーム部リーダー):なめろう→NameChung (@sketch_namerou) | Twitter
会計:ヤミみみ→ヤミみみ (@MtYamaniko) | Twitter
自治会担当者:ぶろっくのいず→ぶろっくのいず (@blocknoise26) | Twitter
2020年度前半(学祭前)
代表者:Bigdra→bigdra (@bigdra50) | Twitter
副代表者:TC→TC (@Meancore226) | Twitter
会計:ヤミみみ→ヤミみみ (@MtYamaniko) | Twitter
自治会担当者:ぶろっくのいず→ぶろっくのいず (@blocknoise26) | Twitter
2020年度後半(学祭後)
???
A-PxLメンバー達のTwitter
部室の変化
2017年度:?
2018年度:会津大学UBIC分室
2019年度:AiCT(あゆむCafe)の展示スペース
2020年度:無し
部名変更の経緯
最初は会津大学VR部という名であったA-PxL。(結局今もVR部と呼んだり呼ばれることも) 2019年3月頃、VRだけでなくARなどxRを扱う部であるのに対し、部名がそぐわないという意見が出る。(※部名の変更がちょうど年度始まりから可能) 「VRやxR関連であること」、「他と被らないオリジナリティのあること」という条件を元に30個?ほどの部名案が出る。その中から「なんちゃらxRなんちゃら(どんな名前だっけ?)」という部名がアンケートで選ばれ、最終的に「Aizu-Progressive xr Lab(略してA-PxL)」という部名になる。A-PxLの読み方は「アイヅピクセル」。
(2020年9月7日更新)