77943


Unity を用いてオリジナルゲームを制作しています。  
プレイヤーの操作するキャラクターに足音を実装する作業を行っており、  
現在は[こちらのサイトを参考](https://acua-piece.com/post/186042580240/game-audio-with-
unity-footsteps)に、キャラクターの足が接触したオブジェクトの tag を検知して  
再生するクリップを切り替えるプログラムを書いています。

これまでに発生していたエラーは初心者の知識でも対処できる単純な物だったので順調に進んでいたのですが、

`CS0029 型'FootStepSEHandler.AudioClips[] を UnityEngine.AudioClip[]に変換できません`

というエラーコードが発生し初めて見るものということもあり、  
何が原因でどこをどのように直せばよいのか一切わからず手詰まりの状態です。

検索をかけてみたりしたのですが、素人に毛が生えたような程度の知識しかないためよくわからず丸投げという形には  
なってしまいますが質問させていただくことにしました。  
お手柔らかにご教示お願いします。

[code]

    public class FootStepSEHandler : MonoBehaviour
    {
        [System.Serializable]
        public class AudioClips
        {
            public string groundTypeTag;
            public AudioClips[] audioClips;
        }
    
        [SerializeField] List<AudioClips> listAudioClips = new List<AudioClips>();
    
        private Dictionary<string, int> tagToIndex = new Dictionary<string, int>();
        private int groundIndex = 0;
    
        protected AudioSource source;
    
        public void PlayFootStepSE()
        {
            AudioClip[] clips = listAudioClips[groundIndex].audioClips;
    
            source.PlayOneShot(clips[Random.Range(0, clips.Length)]);
        }
    }
    
[/code]

※コードは全文ではありません

赤い波線は PlayFootStepSE という関数内の listAudioClips[groundIndex].audioClips
というところに出ています。

`AudioClip[] clips = listAudioClips[groundIndex].audioClips;`


CC BY-SA 4.0
2021-07-03T10:35:48.633
77937
2021-07-03T15:06:46.360
2021-07-03T15:06:46.360
3060
43447
question
c# unity3d visual-studio
"暗黙的に変換できません"というエラーコードの対処方法


`audioClips` フィールドの定義を、以下のように書き換えてみてください。s が無くなって `AudioClips[]` が
`AudioClip[]` になっています。

[code]

    public AudioClip[] audioClips;
    
[/code]

あるいは、この回答の最後の方に書くように `AudioClips` クラス自体を無くしてみてください。

以下、詳しい説明です。

## 暗黙的な変換

「暗黙的に変換できません」というエラーの「変換」というのは、型変換のことです。型変換には明示的なものと暗黙的なものがあります。

明示的な型変換は、型のキャストとも呼ばれ、キャスト式を使って「この値を型として扱ってください」と明示的に型を変換するものです。以下の例では浮動小数点数型の変数
`d` を明示的に整数型に変換しています。

[code]

    double d = 12.3;
    int i = (int)d;
    
[/code]

暗黙的な型変換とは、そうではなくて、プログラムに明示的には書かれていないけれど裏ではこっそり変換が行われているような型変換のことです。よくあるのは代入時に行われるもので、たとえば以下のように書いたときに行われています。

[code]

    double d = 42;
    
[/code]

上のプログラムでは整数リテラルによって表現された整数型の値を浮動小数点数型の変数に代入しようとしています。両者の型は違いますが、整数型から浮動小数点数型へ暗黙の型変換ができるので、暗黙的に浮動小数点数型に型変換されて代入部分の型チェックが通るようになっています。

逆に、以下のように書くと「暗黙的に変換できません」というエラーに繋がります。浮動小数点数型から整数型には暗黙的に型変換できないからです（値の変換に小数点以下の丸めが必要なためです）。この代入をするには明示的に型変換をする必要があります。

[code]

    int i = 12.3;  // このように書くとエラーになる。
    
[/code]

## `AudioClips` は自分自身

いま `FootStepSEHandler.AudioClips` は以下のように定義されています。

[code]

    [System.Serializable]
    public class AudioClips
    {
        public string groundTypeTag;
        public AudioClips[] audioClips;
    }
    
[/code]

ここで、`audioClips` フィールドの型に書かれている `AudioClips` とは、`UnityEngine.AudioClip`
ではなく、今定義がなされている `FootStepSEHandler.AudioClips` 自身を指しています。おそらく想定された型としては
`UnityEngine.AudioClip` が正しくて打ち間違いが起こっていたのでしょうが、再帰的な定義と解釈されてエラーが出なかった訳です。

この状態で、今回エラーが出た行のように `UnityEngine.AudioClip[]` 型の変数に対して `audioClips`
フィールドを代入しようとすると、それは `FootStepSEHandler.AudioClips[]`
型であり、この型は名前が似ているだけで中身は全然異なるものなので暗黙的な型変換が行えず型チェックが失敗し、今回のように「暗黙的に変換できません」というエラーが出る訳です。

こうなってしまうのを回避するため、正しい名前である `AudioClip` と書けば、今回のエラーは出なくなるはずです。

もっというと、`FootStepSEHandler.AudioClips` は不要なクラスかもしれません。今回やりたいことにはそれぞれの
`groundTypeTag` ごとに `UnityEngine.AudioClip[]` があれば充分なので、`groundTypeTag`
をキーとして覚えておけば充分ではないでしょうか。つまり、タグから直接 `UnityEngine.AudioClip[]` が取得できる仕組みです。

[code]

    Dictionary<string, List<AudioClip>> tagToAudioClips = new Dictionary<string, List<AudioClip>>();
    
[/code]

あるいはシリアライズが欲しければ以下のようなものも考えられます。

[code]

    List<List<AudioClip>> tagToAudioClips = new List<List<AudioClip>>();
    List<string> tags = new List<string>();  // あるいは enum でも。
    
[/code]


CC BY-SA 4.0
2021-07-03T14:43:49.050
77943
2021-07-03T14:43:49.050
19110
77937
answer