質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

モーションの現在の再生時間と全体の長さが知りたい、攻撃コンボを実装させたい。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 262

syoshinsya_

score 255

void Update();部ですが攻撃モーションのコンボを作りたくて一定の間隔ないでZキーを押すと振り戻す前の攻撃コンボ2が再生されるという仕様を実装しようと思うのですが現在のモーション時間を知りたいです。調べるとfloat f += Time.deltatime;を使う方法を参考サイトで調べましたがちょと違う?適当?に思うのでモーションの再生時間が知りたいです。また参考サイト2はちょっとやり方が違うみたいで参考にならないです。
参考サイト: https://gametukurikata.com/program/continuityattack

イメージ説明

using UnityEngine;
//using System.Collections.Generic;
using System.Collections;

public class Controller : MonoBehaviour
{

    /* Ik 関係
    Vector3 rightFootPos = new Vector3(0, 0, 0);
    Vector3 leftFootPos = new Vector3(0, 0, 0);

    Quaternion rightFootRot = new Quaternion(0, 0, 0, 0);
    Quaternion leftFootRot = new Quaternion(0, 0, 0, 0);

    bool isRightFootIK = false;
    bool isLeftFootIK = false;

    float RightIkWeight = 0;
    float LeftIkWeight = 0;

    Vector3 rayPositionOffset = new Vector3(0, 0, 0);
    float rayRange = 1.0f;
    float offset = 0.1f;

    */
    private Vector3 vt;
    private float combo_time = 0;
    private float input_h;
    private float input_v;
    private Vector3 move;

    private float walk_speed;//移動速度
    private Vector3 move_direction;//移動方向
    private CharacterController cc;
    private Animator anim;

    /*判定*/
    private bool isAttack = false;
    private bool isAttack_start = false;
    private bool isAttack_end = false;

    private bool isJump = false;
    private bool isGround = true;
    private AnimatorClipInfo[] ClipInfo;
    public GameObject []effects;

  //  public GameObject p;
    private GameObject GroundCheck;
    public Transform LeftHand_IK;//
    //public GameObject LeftHand_target;//
    //private Transform LeftHand_IK = LeftHand_target;
    private readonly int all_effects = 4;

    float j;


    private bool []combo = new bool[4];

    private float comboTime = 1;


  //  public GameObject groundCheck;
    // Use this for initialization
    void Start()
    {
        j = 0;
        move = new Vector3(0, 0, 0);
        cc = GetComponent<CharacterController>();
        anim = GetComponent<Animator>();
        walk_speed = 7;
        ClipInfo = anim.GetCurrentAnimatorClipInfo(0);



        for (int i = 0; i< all_effects; i++)
        {
            combo[i] = false;
        }


        GroundCheck = transform.Find("GroundCheck").gameObject;
        GroundCheck.GetComponent<Ground>().isGround = false;

    }   




    void Move_Mng()
    {

        input_h = Input.GetAxis("Horizontal");
        input_v = Input.GetAxis("Vertical");
        Vector3 move_z = new Vector3();
        Vector3 move_x = new Vector3();
        move_z = Vector3.Scale(Camera.main.transform.forward, new Vector3(1, 0, 1)).normalized * input_v;
        move_x = Camera.main.transform.right * input_h;
        move_direction = move_x + move_z;
        move_direction.y = 0;

        move.x = move_direction.x * walk_speed;
        move.z = move_direction.z * walk_speed;

     //   Debug.Log("move.x: \n" + move.x);
     //   Debug.Log("move.z: \n" + move.z);
        if (move_direction != Vector3.zero)
        {
            move_direction.y = 0;
            transform.rotation = Quaternion.LookRotation(move_direction.normalized);
        }



        /*ジャンプ*/
        if(isJump == true)
        { 
            Debug.Log("aaa");
           move.y += 2;
            if(move.y > 40)
            {
                isJump = false;
            }

        }else if (GroundCheck.GetComponent<Ground>().isGround == false && isJump == false)
        {
            move.y = - 20;
        }


    }

    void Animator_Mng()
    {

        anim.SetFloat("move_forward", getInput());


    }

    float getSpeed()
    {
        return Mathf.Abs(Mathf.Sqrt(Mathf.Abs(move.x * move.x) + Mathf.Abs(move.z * move.z)));
        //        return 100;//Mathf.Abs(Mathf.Sqrt( Mathf.Abs(move.x * move.x) + Mathf.Abs(move.z * move.z)));
    }

    float getInput()
    {
        return Mathf.Abs(Mathf.Sqrt(Mathf.Abs(input_h * input_h) + Mathf.Abs(input_v * input_v)));
        //        return 100;//Mathf.Abs(Mathf.Sqrt( Mathf.Abs(move.x * move.x) + Mathf.Abs(move.z * move.z)));
    }

    //IKの重みを設定する
    void SetIkWeight(AvatarIKGoal _goal, float _posWeight, float _rotWeight)
    {
        anim.SetIKPositionWeight(_goal, Mathf.Clamp(_posWeight, 0.5f, 1.0f));
        anim.SetIKRotationWeight(_goal, Mathf.Clamp(_rotWeight, 0.5f, 1.0f));
    }

    //IKを指定して固定させる
    void SetIk(AvatarIKGoal goal, Vector3 _pos, Quaternion _rot, bool isAddIKPosition = false)
    {
        if (isAddIKPosition)
            _pos += anim.GetIKPosition(goal);

        anim.SetIKPosition(goal, _pos);
        anim.SetIKRotation(goal, _rot);
    }


    IEnumerator combo_corutine_end()
    { 


        yield return new WaitForSeconds(0.5f);
        for (int i = 0; i < all_effects; i++)
        {
            combo[i] = false;
        }

    }

    IEnumerator combo_corutine(int number)
    {
        Instantiate(effects[number], transform.position, transform.rotation);

        anim.SetTrigger("attackCombo_1");


        yield return new WaitForSeconds(0.5f);

        combo[number] = false;
    }


    // Update is called once per frame
    void Update()
    {
        ClipInfo = anim.GetCurrentAnimatorClipInfo(0);

        /*ジャンプ処理*/
        if ( Input.GetKey(KeyCode.Space) == true )//&& GroundCheck.GetComponent<Ground>().isGround == true && isJump == false)
        {
            Debug.Log("Jump");

            //       anim.SetTrigger("jump");

            isJump = true;

        }else //if(isJump == true && GroundCheck.GetComponent<Ground>().isGround == false)
        { 

        }


        if (Input.GetKeyDown(KeyCode.Z) == true ) //&& (ClipInfo[0].clip.name == "EllenIdle") )
        {
            isAttack = true;
            combo[0] = true;
        }else
        { 
            isAttack = false;
        }











        if (Input.GetKey(KeyCode.LeftShift) == true || Input.GetKey(KeyCode.RightShift) == true)
        {
            anim.SetBool("Run_shift", true);

        }
        else
        {
            anim.SetBool("Run_shift", false);

        }





    }


    //////////////////////////////////////////////////////////////////////////////////////////////    
    void FixedUpdate()
    {
        Move_Mng();

        Animator_Mng();




        cc.Move(move * Time.deltaTime);



    }
    //////////////////////////////////////////////////////////////////////////////////////////////




    private void OnAnimatorIK()
    {
        Debug.Log("aaa");


        anim.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1);
        anim.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1);

        anim.SetIKPosition(AvatarIKGoal.LeftHand, LeftHand_IK.position);
        anim.SetIKRotation(AvatarIKGoal.LeftHand, LeftHand_IK.rotation);


        /*
        //右手を固定
        if (LeftHand_IK != null)
        {
            SetIkWeight(AvatarIKGoal.LeftHand, 1.0f, 1.0f);
            SetIk(AvatarIKGoal.LeftHand, LeftHand_IK.position, LeftHand_IK.rotation);
        }
        */

    }


    void MeleeAttackStart()
    {

    }

    void MeleeAttackEnd()
    {

    }


}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

現在のアニメーション時間は
anim.GetCurrentAnimatorStateInfo(0).normalizedTime
で取得できます。normalizedなので0から1の値になります。

現在どのアニメーションが再生されているか(どのステートにいるか)は
anim.GetCurrentAnimatorStateInfo(0).IsName("State名")
がtrueかfalseかで判断できます。

コルーチンでコンボを繋げるなら例えばこんな感じです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Teratail : MonoBehaviour
{
    static readonly int NumCombo = 2;//最大コンボ数
    Animator animator;
    bool isAttack = false;//攻撃中かどうか

    void Start()
    {
        animator = GetComponent<Animator>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Z) && !isAttack)//攻撃中でないときにZキーが押された
        {
            StartCoroutine(Combo());//コンボスタート
        }
    }

    IEnumerator Combo()
    {
        isAttack = true;

        bool nextCombo = true;//コンボが繋がるかどうか
        for (int i = 1; nextCombo && i <= NumCombo; i++)
        {
            nextCombo = false;
            animator.SetTrigger("NextCombo");//i番目のコンボ開始
            yield return new WaitForSeconds(0.1f);
            while (animator.GetCurrentAnimatorStateInfo(0).normalizedTime < 1f)//コンボiの間
            {
                if (Input.GetKeyDown(KeyCode.Z)) nextCombo = true;//キーが押されたらコンボが繋がる
                yield return null;
            }
            yield return new WaitForSeconds(0.3f);//次の攻撃は0.3秒後
        }

        animator.SetTrigger("EndCombo");
        isAttack = false;
    }
}

アニメーターはこうなります。
イメージ説明

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/03/29 13:20

    コルーチンを使ってアニメイベントを使って終わって0.3秒後くらいにアニメーションを始めるっていう手法はどうなのでしょうか?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • トップ
  • C#に関する質問
  • モーションの現在の再生時間と全体の長さが知りたい、攻撃コンボを実装させたい。