20220117のUnityに関する記事は4件です。

UnityでDOTweenしようの際に、DOFadeがエラーとなる

はじめに 嵌ったので備忘として記録 エラー内容 【ソース】 public void FadeOut() { canvasGroup.DOFade(1, fadeTime) } 【エラー】 CS1929 'CanvasGroup' に 'DOFade' の定義が含まれておらず、最も適している拡張メソッド オーバーロード 'ShortcutExtensions.DOFade(Material, float, float)' には 'Material' 型のレシーバーが必要です。 候補にも表示されない状況でした。 解消方法】 パッケージマネージャーから再度インポートを行って、再セッティングしたらエラーが消えました。 さいごに 原因は不明でしたが依存関係か何かがおかしくなってしまったと思われます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Unity】 Addressables.LoadResourceLocationsAsync を使って同じラベルのデータを読み込む

環境 Unity 2020.3.18f1 Addressables 1.18.19 手順 今回は検証のためいらすとやからいくつか素材をダウンロードして使います。 また、検証で作ったプロジェクトはGithubに上げております。 アセットの登録 Windows > Asset Management > Addressables > Groups で設定ウィンドウを開く ダウンロードした素材をドラッグ&ドロップして登録 Labels > Manage Labels でラベルの管理ウィンドウを開く 「+」ボタン押して付けたい名前を入力。ここではOnePieceにします。 一括選択してラベルをつける これでアセットの登録が完了です。 スクリプトの作成 今回は「ボタンを押したらロードを開始して、読み込んだアセット毎をログで出力する」というスクリプトを作る。 LoadAsset.cs using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.EventSystems; public class LoadAsset : MonoBehaviour, IPointerClickHandler { public async void OnPointerClick(PointerEventData eventData) { // タイプ指定しない場合Texture2Dアセットもロードされてしまい、その後のLoadAssetでエラーになる // var locations = await Addressables.LoadResourceLocationsAsync("OnePiece").Task; var locations = await Addressables.LoadResourceLocationsAsync("OnePiece", typeof(Sprite)).Task; foreach (var location in locations) { Addressables.LoadAssetAsync<Sprite>(location).Completed += (op => { Debug.Log($"{op.Result.name} loaded"); }); } } } ここで大事なのは、Addressables.LoadResourceLocationsAsyncを使うときに、第2引数のtypeはデフォルトでnullとなっていますが、タイプをしていない場合、図のようにロケーションの取得で同じアセットが複数回登場してしまうことがある。 特にイメージアセットの場合は、同じアセットがSpriteとTexture2Dの2種類としてカウントされているようです。 終わりに Addressable.LoadResourceLocationsAsyncでアドレスを取得するときにあらかじめタイプを指定するか、 取得したアドレスに対して読み込むときに if (location.ResourceType == typeof(Sprite)) で型のチェックをした方が無難でしょう。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ゲーム動画の視聴者だけが見えるスコア表を配信する(ライブ配信動画と同期したデータ配信)

ゲームのライブ配信動画で「データ放送」を行う ゲームのライブ動画(実況配信)では、プレイヤーがスクリーンに表示している映像がそのままストリーミング動画として配信されます。 そのため、対戦ゲームにおける戦績表やキャラクターのビルド情報などは、プレイヤーがメニュー画面を開いた時や、対戦が終わった時だけ表示されることになります。 配信を途中から見始めた動画視聴者は、「この大会の戦績は今どうなっているんだろう?」「このプレイヤーのキャラビルドはどうなんだろう?」と思っても、配信者がその画面を表示しない限りは分かりません。 ライブ動画はゲームプレイのキャプチャですから、当たり前といえばその通りです。しかし、動画を再生しているブラウザ上で、上から文字や画像を重ねて情報を表示できるとしたらどうでしょうか? 簡単なデモを作りました。 このデモは、カプセル君が剣で刺しあうだけの非常にシンプルなゲームです。Unityで動作しており、その様子をキャプチャして、ストリーミング動画としてブラウザで視聴しています。 左上の「Show Record」ボタンはブラウザ上で描画されているものです。 動画視聴者は、このボタンを好きなときにクリックして、ゲームの情報を閲覧できます。このデモではプレイヤー同士が相手を攻撃した回数をリアルタイムで配信しています。 これを拡張すると、動画視聴者が好きな時に戦績を見たり、キャラクターのビルドを見たり、その他ゲーム内部のリアルタイム情報を自由に閲覧できる「インタラクティブなゲームの動画配信」が実現できます。 本投稿では「Genvid SDK」を使い、ゲームのライブ動画に視聴者だけが見れる「戦績」を重ねて表示する方法について紹介します。 Genvidについて Genvidは、インタラクティブなライブ配信を実現するSDKです。 https://www.genvidtech.com/ja/ Genvidはクラウドサーバー上で動かすサーバミドルウェアと、ブラウザ側で動画と同期した通信処理を行うJavaScriptライブラリで構成されています。 jsライブラリが動作できる環境であれば配信アプリやプラットフォームは問わず使用でき、主にFacebookとTwitch上で使用されています。 最近では、Facebook Gamingで配信されている『PAC-MAN COMMUNITY』のなかで、視聴者をゲームに招待できるゲーム配信者向けの機能「Play with Streamer」で使用されています。 https://www.facebook.com/fbgaminghome/blog/pac-man-community また、このゲームにはFacebook Interactivesを利用した[Watch]タブが用意されています。このタブでは、Facebook Gamingストリーマーによるゲームのライブ配信を楽しめます。Watchモードでは、迷路がUnreal Engineを利用した3Dストリーミングに変わり、視聴者は動画プレイヤーと直接対話してどちらの側に付くかを決めたり、AI PAC-MANやゴーストをパワーアップさせて競い合わせることができます。 このタイトルではブラウザ上のゲームはHTMLで動作し、Watchタブで表示される動画はサーバー上でUnreal Engine 4を使って描画されています。 そのほかの事例として、Unityを使いFacebook上で配信されている「Rival Peak」と、UE4を使った「Project Raven」があります。 今回のデモではGenvid SDK for Unityを使っていますが、Unreal Engine 4でも利用可能です。 Genvidのシステムは、AWSまたはAzureのWindowsクラウドサーバー上で動作させ、動画データをTwitchに送信します。また、動画視聴者のブラウザに対してゲーム内のデータをブロードキャストします。 Windowsを使う理由はここでゲームのexeも動作させるからです。GenvidSDKがサーバー上で動画のエンコードとTwitchへの送信、動画視聴者のブラウザへのデータ配信や、逆にブラウザからのデータを収集を行い、ゲームexeに渡します。 プレイヤーが遊ぶゲームは、ローカルのPCやスマホ、ゲーム機などです。Windowsサーバー上のゲームとは、マルチプレイヤーと同じ仕組みで接続します。P2PでもPhoton Cloudのようなサービスでもかまいません。 Genvidは「Windowsクラウドサーバー上でゲームのexeを動作させる」システムなので、開発環境はWindows 10または11となります。 実装解説 Genvid SDKの導入については、Genvidディベロッパーサイトの日本語マニュアルからご確認ください。 https://www.genvidtech.com/for-developers/ SDK同梱の「Cube」サンプル、およびAsset Storeで配布している「Tanks」サンプルで、どのようにGenvidのシステムを利用するかが理解できます。 https://assetstore.unity.com/packages/templates/tutorials/genvidtanks-sample-161598 Genvid Streamについて 今回紹介するGenvid SDK側で使用する機能は「Genvid Stream」と呼ばれるものになります。 以前書いた以下の投稿でも「Genvid Stream」を使用しています。 GenvidでUnityからストリーミング動画と同期したデータ配信を行う https://qiita.com/Takaaki_Ichijo/items/4fbc70e7efdbdef85459 この例では、プレイヤーの位置データを動画と一緒に配信して、ブラウザ上でプレイヤーの位置と同期したラベルを出しています。 デモ カプセル君が剣で刺しあうだけです。UIは何もありませんが、それぞれのカプセル君は攻撃がヒットした回数を内部的に保持しています。 その内部データを動画と一緒にデータ配信し、ブラウザ上で表示させます。 ブラウザ側の実装 動画視聴サイトは一般的な動的Webページ同様、html, javascript, cssファイルで構成します。 TwitchでGenvidを使用する場合は、「Twitch Extensions」と呼ばれる仕組みを使って実装します。 それぞれのファイルとGenvidの通信モジュールであるgenvid.umd.jsは同一ディレクトリにあるものとします。 (genvid.umd.jsはGenvidインストールフォルダのapi\web\distにあります。) index.html htmlにはビデオの表示と、その上に重ねて表示するボタンとラベル、ラベル表示の下地になるcanvas要素を配置します。 "record_area"ブロック単位で表示・非表示を管理します。 index.html <!doctype html> <html> <head> <title>Genvid Overlay</title> <link rel="stylesheet" href="style.css"> </head> <body> <div class="overlay-layer"> <div id="video_player"></div> <div id="record_area"> <canvas id="record"></canvas> <div class="label" id="player1_score">Player1:10</div> <div class="label" id="player2_score">Player2:10</div> </div> <div class="button" id="show_record">Show Record</div> </div> <script src="genvid.umd.js"></script> <script src="overlay.js"></script> </body> </html> style.css cssファイルにはボタン、ラベル、canvasの設定をしていきます。 ポイントはpositionにabsolute属性を指定することで、これによってビデオの上に各要素を重ねて表示させます。 style.css body { background-color: black; } .button { cursor: pointer; position: absolute; top: 10px; left:10px; padding: 4px; opacity: 0.7; border-radius: 8px; background-color:greenyellow; font-size: medium; } .button:active { opacity: 1; } .label { position: absolute; top:50px; left:10px; font-size: xx-large; margin-top: 0px; } .overlay-layer { position: relative; } .overlay-layer canvas { position: absolute; top: 0; left: 0; } overlay.js Genvidとの通信とCanvasの表示などを制御します。 まずは、canvasの描画とボタンとラベルの設定です。 canvasをfillStyleで灰色の半透明色に塗りつぶし、サイズをウィンドウの横幅基準で調整します。 また、プレイヤーの成績を表示するラベルの要素を取得し、位置調整をします。 最後にrecord_areaブロックをいったん非表示にし、ボタンのクリックで表示・非表示をスイッチさせます。 overlay.js var canvas = document.getElementById('record'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.fillStyle = "rgba(" + [200, 200, 200, 0.7] + ")"; ctx.fillRect(10, 10, window.innerWidth * 0.6, window.innerWidth * 1.6); } var player1_score = document.getElementById('player1_score'); var player2_score = document.getElementById('player2_score'); player2_score.style.marginTop = "40px"; var menu = document.getElementById('record_area'); menu.hidden = true; var button = document.getElementById('show_record'); button.addEventListener("click", function () { menu.hidden = !menu.hidden; }) その後、Genvidの初期化とラベルの書き換え処理を指定します。 genvidClientを作成し、onStreamsReceivedでゲームからJSONデータが送信されてきた際にパースを行い、onDraw(描画更新タイミング)でdraw関数をコールします。 draw関数では、先ほど取得したラベルの参照に対して文字を書き換える処理を行っています。 overlay.js var genvidClient; fetch("/api/public/channels/join", { method: "post" }) .then(function (data) { return data.json() }) .then(function (response) { genvidClient = genvid.createGenvidClient(response.info, response.uri, response.token, "video_player"); genvidClient.onStreamsReceived(function (dataStreams) { for (let stream of [...dataStreams.streams, ...dataStreams.annotations]) { for (let frame of stream.frames) { try { frame.user = JSON.parse(frame.data); } catch (e) { console.log(e, frame.data); } } } }); genvidClient.onDraw(function (frame) { let gameDataFrame = frame.streams["GameRecord"]; if (gameDataFrame && gameDataFrame.user) { draw(gameDataFrame.user); } }); genvidClient.start(); }) .catch(function (e) { console.log(e) }); function draw(gameData) { player1_score.innerText = "Player1: " + gameData.player1Score; player2_score.innerText = "Player2: " + gameData.player2Score; } Unity側の実装 カプセルのキャラクター制御はNavMeshAgentで適当に動かしているだけなので、説明は省略します。 プレイヤーの点数を管理する「PlayerScore」クラスのパブリックフィールド「Score」に攻撃を当てた回数を保持しているものとします。 MatchController.cs public class MatchController : MonoBehaviour { public List<PlayerScore> playerScoreList = new List<PlayerScore>(); public void SubmitGameRecord(string streamId) { if (GenvidSessionManager.IsInitialized && GenvidSessionManager.Instance.enabled) { GameRecord gameRecord = new GameRecord () { player1Score = playerScoreList[0].Score, player2Score = playerScoreList[1].Score, }; GenvidSessionManager.Instance.Session.Streams.SubmitGameDataJSON (streamId, gameRecord); } } [System.Serializable] public struct GameRecord { [SerializeField] public int player1Score, player2Score; } } SubmitGameRecordメソッドは、GenvidのGenvidStreamsインスタンスから呼び出すものです。GameRecord構造体を経由してJSONに変換し、サーバーへ送信します。 サーバーは、タイムコードを加えてブラウザへ動画と共にデータを配信します。 シーンに配置したGenvidStreamsプレハブで、ID「GameRecord」を作成し、On Submit Streamのリスト経由でSubmitGameRecordメソッドを呼ぶように設定します。 動作テスト 以上のスクリプトはオーバーレイ部分と、Unityからデータを送信する部分のみの例です。 Genvidサーバーを動作させるには、webサーバーを立てたり、Genvidシステムを動作させるための各種設定ファイルが必要です。 クラウドサーバーを使わず、PCの中でテスト実行する場合は、SDKに同梱されている「cube」サンプルから設定ファイルを流用することで動作させることができます。 ローカルクラスタの開始 https://www.genvidtech.com/doc/ja/SDK-1.32.0/development_guide/game_integration/utilisation.html Genvid操作用pythonスクリプトのgenvid-toolboxのインストール 基盤システムGenvid bastionのインストール システム環境変数「GENVID_STATIC_BINDING」をtrueに設定してポート固定 作業用ディレクトリを作り、/publicに作成したhtml,css,js,genvid.umd.jsを配置 /app/BuildにUnityからビルドしたデータ一式を配置 「cube」サンプルからbackendフォルダ、configフォルダ、templatesフォルダ、package.json、Web.pyをコピーして作業用ディレクトリに配置 templates\local\unity.nomad.tmplの「unity_Cube.exe」をビルドしたexe名に変更 web.pyから web.py dict(name="stream", required=True), dict(name="web", required=True), を削除 コマンドプロンプトやPowerShellで作業ディレクトリに移動してnpm install 応用 今回はゲームからデータを配信し、ブラウザ上で表示させるものでした。Genvidでは、動画視聴者の入力を収集し、ゲーム側に渡すこともできます。 これらを組み合わせることによって、ゲームの動画配信をインタラクティブなコンテンツに昇華することが可能です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ベジェ曲線の放電線をShaderGraphで描画する (SGL005)

VFX力を上げていきたいので模写ログ. 完成品 全体像 VFX Graph VFX ShaderGraph ShaderGraphの方は、電気線の両端をきれいにアンチエイリアスかけてフェードアウトするために利用. 作り方 ただの模写なので、本家をみてください..! 雑にブロック解説 Spawn - SingleBurst: 256個生成 InitializeParticleStrip - particleはつなげて先表示する - SetProgressでi/255のfloat値をセットして、後のベジェ曲線の補完位置Tで利用 UpdateParticleStrip - SetPositionで位置の更新 (particleの順番ごとにベジェ曲線の補完位置をそれぞれ代入) - AddPositionでパーリンノイズをベジェ曲線位置に対してランダムに追加. このノイズ部分がアニメーションする Output ParticleStrip Quad - ScreenSpaceSizeでスクリーンスペースに対して、いい感じに細いピクセルラインを引く - ShaderGraphは両端をいい感じにエイリアスかけるようにしたものを参照 SetProgress - GetAttribute: attributeIndexInStripでStripLineのindexを取得して0-1のprogressに直してセットしておく. (あとで使う) Bezier Curve Line Positions - ベジェ曲線の位置を算出 - Initializeで設定したSetProgressの値をここで参照して中間位置に設定 SourceTransform/TargetTransform - transformをblackboardのパラメータとして外だしする. - ベジェ曲線の高さもパラメータとして外出しする. - transform(position)と高さから2つのsource position, target positionを生成してベジェ曲線に使う LineNoise - ベジェ曲線に乗せるノイズを生成する - Perlin Noise 3Dでノイズ生成. - ノイズのレンジは中間が多め、先端末端を少なめにするように、SampleCurve+GetProgressで調整. TransformBinding - VFXPropertyBinderを使って、exportしたpropertyのtransformを割り当てる. - これによってオブジェクト位置に連動して先端と終端の放電線の位置が変わる. 感想 VFXPropertyBinderが便利...! ノイズの使い方やVFX ShaderGraphの使い所なんかもすごく勉強になった. 色んな人のやり方勉強できる模写おすすめ..! Youtubeに色々上がってる
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む