20210610のUnityに関する記事は3件です。

UnityWebRequestはちゃんとSSL証明書エラーを吐いてくれるか

ふと、「中間者攻撃なりBCGハイジャックなり、なんらかの理由で意図したところにアクセス出来てなかった場合、unityちゃん(正確にはUnityWebRequest)はちゃんとエラー吐いてくれるか」が猛烈に気になったため確認した。 なお、特別に証明書のインストール等はしておらず、Windows10環境です。 とりあえず結論 当該記事での検証手順であれば、ちゃんとエラーになった。 手順(簡易) 適当なドメインを取る 当該記事では example.dev で説明します。勿論、こんな買ったら高そうなドメインは自分は持ち合わせておりません。 サブドメ2つ振る test1.example.dev test2.example.dev とします。 nginxサーバを2台立ててlet's encryptでSSL対応 手順は割愛します。ぐぐればすぐ出てくるのでそんなに難しくないです。 立てたサーバにさっきとったサブドメでAレコード設定 ここまでやったらブラウザで https://test1.example.dev https://test2.example.dev アクセスして正常を確認します。 俺(私)たち入れ替わってるー 入れ替える必要まではないんですが test1.example.devの向き先IPをtest2サーバのIPに書き換えます。 反映されたあたりでブラウザアクセスして NET::ERR_CERT_COMMON_NAME_INVALID あたりが出ることを確認します。 unity HTTPメソッドは何でも良いので UnityWebRequest 使って SendWebRequest します。 Curl error 51: Cert verify failed: UNITYTLS_X509VERIFY_FLAG_CN_MISMATCH こんなエラーが出ます。 isNetworkErrorのほうがtrue返すようになりますが、中身吐いてもUnknown Errorです。 結論(2回目) ちゃんとエラーになる。 余談 なんとなく勘付く方もいるかと思いますが、基本的にOSにインストールされている証明書を使うようです。 軽く調べた限りだと、Win/Mac/iOSあたりだとOSにインストールしさえすれば自己署名でもいけるらしいのですが、 androidはアカンようで、その場合検証用の実装を自前で書く必要があるようです。 もしSSL関係でブラウザではいけるのにunityでは証明書の検証エラーが出るような場合この辺りを踏んでるかもしれませんね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Unity]TextureをSwiftのNativePluginから送る

Unity に Texture を Swift の Native Plugin から送る UnityのTextureのポインタをSwiftだけで作ったNative Pluginに渡して処理するの逆の話です ネイティブで作成した Texture を Unity へ送って表示させたい場合があります 例えば、macOS のスクリーンキャプチャの映像を Unity で表示させる事ができます macOS や iOS では、MTLTexture から Texture2D.CreateExternalTexture を使って Texture2D を取得可能です 今回のサンプル リポジトリはこちらです Swift だけで、Unity の iOS の Native Plugin を作る の内容をベースにしています macOS で、スクリーンキャプチャした結果を Cube のテクスチャに貼っています unityでmacのデスクトップキャプチャできた! pic.twitter.com/x2AkZ6z6zF— ふじき (@fzkqi) June 10, 2021 Texture2D.CreateExternalTexture Texture2D.CreateExternalTexture を使うことで、ネイティブのテクスチャオブジェクトから Unity テクスチャを作成できます iOS や macOS の場合は、ネイティブのテクスチャオブジェクトは MTLTexture です そこで、MTLTexture のポインタ、テクスチャの高さと幅を用意します Unityの実装 Native Plugin の定義 width と height のポインタを渡して、ネイティブに代入させます 戻り値として、MTLTexture のポインタを IntPtr として受け取ります [DllImport("mcDesktopCapture")] private static extern IntPtr mcDesktopCapture_getCurrentFrame2(ref int width, ref int height); Texture を取得する 取得したポインタから、Texture2D.CreateExternalTexture を使って Texture を得て設定しています int w = -1; int h = -1; IntPtr texturePtr = mcDesktopCapture_getCurrentFrame2(ref w, ref h); Texture2D texture = Texture2D.CreateExternalTexture(w, h, TextureFormat.ARGB32, false, false, texturePtr); Renderer m_Renderer = GetComponent<Renderer>(); m_Renderer.material.SetTexture("_MainTex", texture); Swift の実装 @_cdecl を付けて、C# で作成した関数を実装します ref を UnsafeMutablePointer として、IntPtr を UnsafeMutableRawPointer として読み替えます width と height にテクスチャの大きさを設定します retain してテクスチャのポインタを返します @_cdecl("mcDesktopCapture_getCurrentFrame2") public func mcDesktopCapture_getCurrentFrame2(_ width: UnsafeMutablePointer<Int64>, _ height: UnsafeMutablePointer<Int64>) -> UnsafeMutableRawPointer { let texture: MTLTexture = getTexture() width.initialize(to: Int64(texture.width)) height.initialize(to: Int64(texture.height)) return Unmanaged.passRetained(texture).toOpaque() } 破棄が必要な場合は、takeRetainedValue を使います @_cdecl("mcDesktopCapture_clearFrame") public func mcDesktopCapture_clearFrame(_ texturePtr: UnsafeMutableRawPointer) { _ = Unmanaged<MTLTexture>.fromOpaque(texturePtr).takeRetainedValue() } ライブラリの出力と設定 こちらの記事の Framework でビルドする の章以降と同じ手順で実行ビルド可能です 作成した ライブラリ を Unity のプロジェクトにコピーして、Texture を取得できていることを確認します おわりに Texture2D.CreateExternalTexture を使うことで、Swift だけで作ったライブラリから、Unity へ Texture を送る仕組みを実装できました CreateExternalTexture を関連する関数に、UpdateExternalTexture があり、Texture の作成だけでなく、更新も可能です Swift から Unity に Texture を送る仕組みは、応用の幅が広いので、活用して行きたいです
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

敵のダメージリアクション・バリエーション

バトルがあるゲームの爽快感の重要な要素といえば、やっぱり敵のリアクションです(断言) 3Dゲームにおける敵のダメージリアクションといえば、ダメージモーションを再生するのが一般的・・・と思いきや、ダメージモーションって地味に取り回しが悪いですよね。 確かにリアクションとしては一番丁寧な演出なのですが、モーションを流す以上、攻撃や移動などのモーションを中断しないといけないので演出の充実として実装するにしてはゲーム仕様側への影響が大きく、気軽に入れるわけにはいけません。 そんなわけで一般的にはダメージモーションは大技を当てた時や、部位破壊的な特殊な状態になったときなど、「仕様に伴う特別な演出」で再生されることが多い印象です。 とはいえ一番頻度の高い「小さなダメージを与えた時」の演出が無いと爽快感がないどころか、攻撃が効いてるのかどうか分からない、なんてことになりかねません。 ↑効いてる?弾かれてる? 市場のゲームでは「細かいダメージを与えた時の汎用演出」が用意されてて、いろいろあるなぁと思ったので自分が知ってるものを引き出しとして実装してみました。 ■備考 本記事では演出の組み立てにDOTweenを使ってますが、同じ演出をAnimationでもベタ書きでも作れます 点滅によるダメージ表現 まずは点滅。もはや古典と言える演出ですが、攻撃が当たった結果何かが起きたことの分かりやすさはバッチリ。 RendererのON/OFFで完結するので負荷も低い(というかなんなら一時的に軽くすらなるのでは)ので、その辺は古くからの演出ならではですね。 これを汎用演出とすると他の演習も合わせてレトロなものにしないと異物感が大きいので、あえてそういう路線を攻めたりしない限りは他の演出を使ったほうが良さそう。 Enemy.cs using UnityEngine; using DG.Tweening; public class Enemy : MonoBehaviour { /// <summary> モデルのRenderer </summary> [SerializeField] private Renderer _renderer; private Sequence _seq; private void OnTriggerEnter(Collider other) { HitBlink(); } /// <summary> 点滅によるダメージ演出再生 </summary> private void HitBlink() { _seq?.Kill(); _seq = DOTween.Sequence(); _seq.AppendCallback(() => _renderer.enabled = false); _seq.AppendInterval(0.07f); _seq.AppendCallback(() => _renderer.enabled = true); _seq.AppendInterval(0.07f); _seq.SetLoops(2); _seq.Play(); } } 赤のカラー乗算によるダメージ表現 3Dゲームの黎明期に主流だったような印象のある演出。 古臭さも薄く、実装も簡単でわかりやすいので今でも一定数見られるものだと思います。 難点としては、色の乗算なのでモデル自体が黒に近かったり、暗めの雰囲気を作っているゲームでは変化が目立ちづらいこと。 場合によっては汚れてるような印象にもなりうるので、時間が許すならもう少し踏み込んだ演出を作りたいところ。 Enemy.cs using UnityEngine; using DG.Tweening; public class Enemy : MonoBehaviour { /// <summary> マテリアルの色パラメータのID </summary> private static readonly int PROPERTY_COLOR = Shader.PropertyToID("_Color"); /// <summary> モデルのRenderer </summary> [SerializeField] private Renderer _renderer; /// <summary> モデルのマテリアルの複製 </summary> private Material _material; private Sequence _seq; private void Awake() { // materialにアクセスして自動生成されるマテリアルを保持 _material = _renderer.material; } private void OnTriggerEnter(Collider other) { HitFadeBlink(Color.red); } /// <summary> カラー乗算によるダメージ演出再生 </summary> private void HitFadeBlink(Color color) { _seq?.Kill(); _seq = DOTween.Sequence(); _seq.Append(DOTween.To(() => Color.white, c => _material.SetColor(PROPERTY_COLOR, c), color, 0.1f)); _seq.Append(DOTween.To(() => color, c => _material.SetColor(PROPERTY_COLOR, c), Color.white, 0.1f)); _seq.Play(); } } 白のカラー加算によるダメージ表現 最近よく見る演出。 加算で色を与えるのでモデルや画面の色味に左右されづらく、綺麗でわかりやすいです。 特にこだわりがなければこれが一番安定だと思います。 サンプルコードでは、[Create] > [Shader] > [Standard Surface Shader] で加算カラーを与えられるシェーダーを作っています。 プロパティ名は _AdditiveColor です。 StandardSurface-Additive.shader Shader "Custom/StandardSurface-Additive" { Properties { _Color ("Color", Color) = (1,1,1,1) _MainTex ("Albedo (RGB)", 2D) = "white" {} _AdditiveColor ("Additive Color", Color) = (0,0,0) // 加算カラーのプロパティ追加 _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; fixed4 _Color; fixed3 _AdditiveColor; // 加算カラーのメンバ定義 UNITY_INSTANCING_BUFFER_START(Props) UNITY_INSTANCING_BUFFER_END(Props) void surf (Input IN, inout SurfaceOutputStandard o) { fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb + _AdditiveColor.rgb; // 加算カラーを与える o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" } 上記のStandardSurface-Additive.shaderを敵モデルのマテリアルに与え、下記コードで明滅させます。 Enemy.cs using UnityEngine; using DG.Tweening; public class Enemy : MonoBehaviour { /// <summary> マテリアルの加算色パラメータのID </summary> private static readonly int PROPERTY_ADDITIVE_COLOR = Shader.PropertyToID("_AdditiveColor"); /// <summary> モデルのRenderer </summary> [SerializeField] private Renderer _renderer; /// <summary> モデルのマテリアルの複製 </summary> private Material _material; private Sequence _seq; private void Awake() { // materialにアクセスして自動生成されるマテリアルを保持 _material = _renderer.material; } private void OnTriggerEnter(Collider other) { HitFadeBlink(Color.white); } /// <summary> カラー加算によるダメージ演出再生 </summary> private void HitFadeBlink(Color color) { _seq?.Kill(); _seq = DOTween.Sequence(); _seq.Append(DOTween.To(() => Color.black, c => _material.SetColor(PROPERTY_ADDITIVE_COLOR, c), color, 0.1f)); _seq.Append(DOTween.To(() => color, c => _material.SetColor(PROPERTY_ADDITIVE_COLOR, c), Color.black, 0.1f)); _seq.Play(); } } スケールの拡大・縮小によるダメージ表現 色ではなく動きで表現するダメージ演出。 カラー乗算・加算と組み合わせで使われることが多いかも。 多めの敵で使うと画面上の変化量が大きすぎて、大げさに見えたり違和感があったりするので相性は悪いですが、1〜3頭身くらいのキャラ向けには向いてる演出だと思います。 Enemy.cs using UnityEngine; using DG.Tweening; public class Enemy : MonoBehaviour { /// <summary> 拡大・縮小するTransform </summary> [SerializeField] private Transform _model; private Sequence _seq; private void OnTriggerEnter(Collider other) { HitScaleBound(); } /// <summary> スケールの拡大・縮小によるダメージ演出再生 </summary> private void HitScaleBound() { _seq?.Kill(); _seq = DOTween.Sequence(); _seq.Append(DOTween.To(() => Vector3.one, scale => _model.localScale = scale, Vector3.one * 1.05f, 0.07f)); _seq.Append(_model.DOScale(1f, 0.07f)); _seq.Play(); } } のけぞり(ボーン回転)によるダメージ表現 本記事で紹介したかった本命のダメージ演出! これ実は FF7 REMAKE で使われてた表現で・・・早い話がパクったネタです。 (バレットで敵に連射してるときにいい感じにガクガクしてて気持ちよかった) 攻撃によって特定のボーン(人型なら腰あたりが良い)を傾け、のけぞるような演出を与えています。 使用するボーンの選定や傾けかたをモデルごとに決めたり、量産時に規則を作ったりとやや配慮が必要ですが、変にモデルの色や大きさを変えない上、攻撃方向に応じたのけぞり方をするので、3Dゲームらしさのある自然な見た目になります。 Enemy.cs using UnityEngine; using DG.Tweening; public class Enemy : MonoBehaviour { /// <summary> のけぞりによるダメージ演出で回転するボーン </summary> [SerializeField] private Transform _waistBone; /// <summary> のけぞりによるダメージ演出によるボーンの回転角度 </summary> private Vector3 _offsetAnglesWaist; private Sequence _seq; private void OnTriggerEnter(Collider other) { // ヒットした攻撃判定の進行方向に向けて体を倒すため、角度を取得 var bulletAngles = other.transform.eulerAngles; // X角度は無視 bulletAngles.x = 0f; HitTiltWaist(Quaternion.Euler(bulletAngles) * Vector3.forward); } /// <summary> のけぞり(ボーン回転)によるダメージ演出を再生 </summary> /// <param name="vector">ヒットした攻撃判定の進行方向</param> private void HitTiltWaist(Vector3 vector) { _seq?.Kill(); _seq = DOTween.Sequence(); // 攻撃判定の進行方向を自身のTransformのローカル座標系に変換 vector = transform.InverseTransformVector(vector); // 攻撃判定の進行方向に向けて10度傾ける // FIXME: Vector3のどの要素に攻撃判定の進行方向ベクトルの各要素を使うか、正/負解釈をどうするかは、モデルのボーン構造に合わせて適宜変更する var tiltAngles = new Vector3(0f, -vector.x, -vector.z).normalized * 10f; _seq.Append(DOTween.To(() => Vector3.zero, angles => _offsetAnglesWaist = angles, tiltAngles, 0.1f)); _seq.Append(DOTween.To(() => tiltAngles, angles => _offsetAnglesWaist = angles, Vector3.zero, 0.2f)); _seq.Play(); } private void LateUpdate() { // Animatorによる今フレームのボーンの角度が決まった後、のけぞりによる回転角度を与える _waistBone.localEulerAngles += _offsetAnglesWaist; } } まとめ 汎用のダメージ演出はゲーム中に一番多く見ることになる演出だと思うので、いかに自然かつ小気味良いものにするか地味に重要な要素だな〜と思います。 「他にこういうのあるよ!」ってのがあったら教えてください!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む