LoginSignup
1
1

More than 5 years have passed since last update.

HOTween、iTween とGoKitのspeedの比較

Posted at

テストの結果:iTween < HoTween < GoKit
コードは以下です。

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using Holoville.HOTween;

public class SpeedTest : MonoBehaviour
{
// ENUMS //////////////////////////////////////////////////

private enum TweenEngine 
{
    None,
    HOTween,
    iTween
    ,GoKit
}

private enum TestType 
{
    Emit,
    Loop,
    YoyoLoop
}

// SETTINGS ///////////////////////////////////////////////

/// <summary>
/// I keep this as a constant because iTween has no "version" field.
/// </summary>
private const   string                              ITWEEN_VERSION = "2.0.45";

private const string  GOKIT_VERSION = "2.0.5";

// VARS ///////////////////////////////////////////////////

/// <summary>
/// Basic tween duration when speed is set to x1.
/// </summary>
public      float                                   twDuration = 4;

private     int                                     numCubes = 0;
private     TweenEngine                             twEngine;
private     TestType                                testType;
private     float                                   timeScale;
private     Quaternion                              startRot = Quaternion.Euler( new Vector3( 20, 20, 20 ) );

private     bool                                    twRunning;

private     string[]                                cubesBarLabels = new string[] {"1","10","50","100","500","1000","2000","3000","4000"};
private     int                                     cubesBarSelIndex = 4;
private     string[]                                timescaleBarLabels = new string[] {"x0.25","x0.5","x1","x2","x4","x8","x16","x32"};
private     int                                     timescaleBarSelIndex = 2;
private     string[]                                engineLabels = new string[] {"None","HOTween v" + HOTween.VERSION,"iTween v" + ITWEEN_VERSION,"GoKit v" + GOKIT_VERSION};
private     int                                     engineSelIndex = 0;
private     string[]                                testTypeLabels = new string[] {"Emit","Loop","PingPong"};
private     int                                     testTypeSelIndex = 0;
private     bool                                    toggleColOut = true;
private     bool                                    togglePos = true;
private     bool                                    toggleRot;
private     bool                                    toggleScale;

private     bool                                    stylesSet;
private     GUIStyle                                cntrdLabelStyle;

private     bool                                    poolManagerOn = false;
public      static     bool                          withGC;

private     List<GoTween>                            goTweens = new List<GoTween> ();

// REFERENCES /////////////////////////////////////////////

private     GameObject                              thisGO; // Reference to this gameObject: stored in order to speed up iTween creation.
private     GameObject                              cubePrefab;
private     Transform                               cubesContainer;
private     List<GameObject>                        cubes; // List of all cubes in the scene.


// ===================================================================================
// UNITY METHODS ---------------------------------------------------------------------

private void Start()
{
    thisGO = this.gameObject;

    // Store the prefab from which all cubes will be created.
    cubePrefab = (GameObject) Resources.Load( "Cube" );
    // Instantiate a parent for all cubes (just to keep the Hierarchy panel clean).
    cubesContainer = new GameObject( "CUBES" ).transform;
    InvokeRepeating ("MemoryGC",1,30);
}


private void MemoryGC(){
    System.GC.Collect ();
}
private void OnGUI()
{
    if ( !stylesSet ) {
        // One time set of GUI styles.
        stylesSet = true;
        GUI.skin.label.wordWrap = false;
        GUI.skin.button.fontSize = GUI.skin.toggle.fontSize = GUI.skin.label.fontSize = 11;
        cntrdLabelStyle = new GUIStyle( GUI.skin.label );
        cntrdLabelStyle.alignment = TextAnchor.UpperCenter;
    }

    // Create the test controls.

    GUILayout.BeginArea( new Rect( 10, 2, Screen.width - 20, Screen.height - 4 ) );
    GUILayout.BeginVertical();
    GUILayout.BeginHorizontal();
    GUILayout.FlexibleSpace();
    GUILayout.BeginVertical();

    GUILayout.BeginHorizontal();
    GUILayout.FlexibleSpace();
    GUILayout.Label( "Cubes" );
    int prevNumCubes = numCubes;
    cubesBarSelIndex = GUILayout.Toolbar( cubesBarSelIndex, cubesBarLabels );
    numCubes = Int32.Parse( cubesBarLabels[cubesBarSelIndex] );
    if ( twRunning && prevNumCubes != numCubes )        StartTweenTest();
    GUILayout.FlexibleSpace();
    GUILayout.EndHorizontal();

    GUILayout.BeginHorizontal();
    GUILayout.FlexibleSpace();
    GUILayout.Label( "Speed" );
    int prevTSIndex = timescaleBarSelIndex;
    timescaleBarSelIndex = GUILayout.Toolbar( timescaleBarSelIndex, timescaleBarLabels );
    timeScale = float.Parse( timescaleBarLabels[timescaleBarSelIndex].Substring( 1 ) );
    if ( timescaleBarSelIndex != prevTSIndex )          StartTweenTest();
    GUILayout.FlexibleSpace();
    GUILayout.EndHorizontal();

    GUILayout.BeginHorizontal();
    GUILayout.FlexibleSpace();
    GUILayout.Label( "Tweens" );
    int prevTotTogs = GetTotToggles();
    toggleColOut = GUILayout.Toggle( toggleColOut, "FadeOut" );
    togglePos = GUILayout.Toggle( togglePos, "Position" );
    toggleRot = GUILayout.Toggle( toggleRot, "Rotation" );
    toggleScale = GUILayout.Toggle( toggleScale, "Scale" );
    if ( prevTotTogs != GetTotToggles() )
        if ( twEngine != TweenEngine.None )             StartTweenTest();
    GUILayout.Space( 20 );
    GUILayout.Label( "Test type" );
    int prevTestTypeInd = testTypeSelIndex;
    testTypeSelIndex = GUILayout.Toolbar( testTypeSelIndex, testTypeLabels );
    testType = (TestType)testTypeSelIndex;
    if ( prevTestTypeInd != testTypeSelIndex )
        if ( twEngine != TweenEngine.None )             StartTweenTest();
    GUILayout.FlexibleSpace();
    GUILayout.EndHorizontal();

    GUILayout.BeginHorizontal();
    GUILayout.FlexibleSpace();
    GUILayout.Label( "Engine" );
    int prevEngineInd = engineSelIndex;
    engineSelIndex = GUILayout.Toolbar( engineSelIndex, engineLabels );
    twEngine = (TweenEngine)engineSelIndex;
    if ( prevEngineInd != engineSelIndex ) {
        Clear();
        if ( twEngine != TweenEngine.None )             StartTweenTest();
    }
    GUILayout.FlexibleSpace();
    GUILayout.EndHorizontal();

    GUILayout.Space( 20 );
    GUILayout.BeginHorizontal();
    GUILayout.FlexibleSpace();
    GUILayout.Label( "WithGC" );
    withGC = GUILayout.Toggle(withGC, "WithGC" );
    //GUILayout.Label( "PoolManagerOn" );

    //poolManagerOn = GUILayout.Toggle( poolManagerOn, "PoolManager" );
    GUILayout.FlexibleSpace();
    GUILayout.EndHorizontal();

    if ( twRunning ) {
        GUILayout.FlexibleSpace();

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if ( GUILayout.Button( "Play" ) )                   Play();
        if ( GUILayout.Button( "Pause" ) )                  Pause();
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        GUILayout.Label( ( twEngine == TweenEngine.HOTween ? "HOTween" : twEngine == TweenEngine.iTween? "iTween":"GoKit" ) + "\n" + numCubes + " tweened cubes, " + GetTotToggles() + " tweeened properties on each cube", cntrdLabelStyle );
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
    }

    GUILayout.EndVertical();
    GUILayout.FlexibleSpace();
    GUILayout.EndHorizontal();
    GUILayout.EndVertical();
    GUILayout.EndArea();
}

// ===================================================================================
// PRIVATE METHODS -------------------------------------------------------------------

/// <summary>
/// Clears any running tween and destroys the cubes.
/// </summary>
private void Clear()
{
    if ( twRunning ) {
        // Kill all HOTweens
        HOTween.Kill();
        //System.GC.Collect();
        // Kill all iTweens
        // (I do it while iterating through each tweened cube, because iTween.Stop() won't work if there are too many cubes).
        foreach ( GameObject cube in cubes ) {
            iTween.Stop( cube );
            //Go.killAllTweensWithTarget(cube);
            Go.killAllTweensWithTarget(cube.transform);
            //Go.Destroy(cube);
            Destroy( cube );
        }

        cubes = null;
    }

    twRunning = false;
}

/// <summary>
/// Clears any running tweens and cubes, and starts a new test.
/// </summary>
private void StartTweenTest()
{
    Clear();

    cubes = new List<GameObject>();
    for ( int i = 0; i < numCubes; ++i )
        NewTween();

    twRunning = true;
}

/// <summary>
/// Creates a new cube and a random tween, based on the current settings.
/// </summary>
private void NewTween()
{
    GameObject cubeGO = (GameObject)Instantiate( cubePrefab, ( togglePos ? Vector3.zero : RandomFromPosition() ), startRot );
    Destroy( cubeGO.GetComponent<BoxCollider>() );
    cubes.Add( cubeGO );
    // Set the cube parent.
    Transform cube = cubeGO.transform;
    cube.parent = cubesContainer;
    // Random color.
    Color startCol = RandomColor();
    Color endCol = startCol;
    endCol.a = 0;
    cube.renderer.material.color = startCol;
    // Random duration.
    float duration = twDuration * 0.5f + UnityEngine.Random.value * twDuration * 0.5f;
    // Settings.
    LoopType hoLoopType = ( testType == TestType.Emit || testType == TestType.Loop ? LoopType.Restart : LoopType.Yoyo );
    int hoLoops = ( testType == TestType.Emit ? 1 : -1 );
    iTween.LoopType iLoopType = ( testType == TestType.Emit ? iTween.LoopType.none : testType == TestType.Loop ? iTween.LoopType.loop : iTween.LoopType.pingPong );
    EaseType hoeaseType = EaseType.EaseInOutSine;
    iTween.EaseType iEaseType = iTween.EaseType.easeInOutSine;

    Go.defaultEaseType = GoEaseType.SineInOut;
    GoLoopType  goLoopType = (testType == TestType.Emit || testType == TestType.Loop ? GoLoopType.RestartFromBeginning : GoLoopType.PingPong);
    int goLoops = (testType == TestType.Emit ? 1 : -1);
    // Duration related to timeScale.
    // HOTween could do this by setting the TimeScale parameter,
    // but to keep both tests similar I won't use it.
    duration /= timeScale;
    // This lets me know when a callback has been added, so I don't do it twice.
    // The callback needs to be added in case of the Emit test type,
    // so that a cube can be destroyed (and a new one created) when the tween is complete.
    bool callbackAdded = false;

    switch ( twEngine ) {
    case TweenEngine.HOTween:
        // HOTWEEN
        if ( toggleColOut ) {
            if ( !callbackAdded && testType == TestType.Emit ) {
                // Add onComplete callback.
                callbackAdded = true;
                HOTween.To( cube.renderer.material, duration, new TweenParms().Prop( "color", endCol ).Ease( EaseType.EaseInSine ).OnComplete( OnHOTweenComplete, cubeGO ) );
            } else {
                HOTween.To( cube.renderer.material, duration, new TweenParms().Prop( "color", endCol ).Ease( EaseType.EaseInSine ).Loops( hoLoops, hoLoopType ) );
            }
        }
        // Since the other animations target is the same, I just create different parms, and than apply them to the cube's transform.
        TweenParms hoParms = new TweenParms().Ease( hoeaseType ).Loops( hoLoops, hoLoopType );
        if ( !callbackAdded && testType == TestType.Emit ) {
            // Add onComplete callback.
            callbackAdded = true;
            hoParms.OnComplete( OnHOTweenComplete, cubeGO );
        }
        if ( togglePos )            hoParms.Prop( "position", RandomToPosition() );
        if ( toggleRot )            hoParms.Prop( "rotation", RandomRotation() );
        if ( toggleScale )          hoParms.Prop( "localScale", RandomScale() );
        // Create a new tween for the cube's transform, and add the parms.
        if ( hoParms.hasProps )     HOTween.To( cube, duration, hoParms );
    break;
    case TweenEngine.iTween:
        // ITWEEN
        if ( toggleColOut ) {
            if ( !callbackAdded && testType == TestType.Emit ) {
                // Add onComplete callback.
                callbackAdded = true;
                iTween.ColorTo( cubeGO, iTween.Hash( "time", duration, "color", endCol, "easetype", iTween.EaseType.easeInSine, "oncomplete", "OniTweenComplete", "oncompletetarget", thisGO, "oncompleteparams", cubeGO ) );
            } else {
                iTween.ColorTo( cubeGO, iTween.Hash( "time", duration, "color", endCol, "easetype", iTween.EaseType.easeInSine, "looptype", iLoopType ) );
            }
        }
        if ( togglePos ) {
            Vector3 randomPos = RandomToPosition();
            if ( !callbackAdded && testType == TestType.Emit ) {
                // Add onComplete callback.
                callbackAdded = true;
                iTween.MoveTo( cubeGO, iTween.Hash( "time", duration, "x", randomPos.x, "y", randomPos.y, "z", randomPos.z, "easetype", iEaseType, "looptype", iLoopType, "oncomplete", "OniTweenComplete", "oncompletetarget", thisGO, "oncompleteparams", cubeGO ) );
            } else {
                iTween.MoveTo( cubeGO, iTween.Hash( "time", duration, "x", randomPos.x, "y", randomPos.y, "z", randomPos.z, "easetype", iEaseType, "looptype", iLoopType ) );
            }
        }
        if ( toggleRot ) {
            if ( !callbackAdded && testType == TestType.Emit ) {
                // Add onComplete callback.
                callbackAdded = true;
                iTween.RotateTo( cubeGO, iTween.Hash( "time", duration, "rotation", RandomRotation().eulerAngles, "easetype", iEaseType, "looptype", iLoopType, "oncomplete", "OniTweenComplete", "oncompletetarget", thisGO, "oncompleteparams", cubeGO ) );
            } else {
                iTween.RotateTo( cubeGO, iTween.Hash( "time", duration, "rotation", RandomRotation().eulerAngles, "easetype", iEaseType, "looptype", iLoopType ) );
            }
        }
        if ( toggleScale ) {
            Vector3 randomScale = RandomScale();
            if ( !callbackAdded && testType == TestType.Emit ) {
                // Add onComplete callback.
                callbackAdded = true;
                iTween.ScaleTo( cubeGO, iTween.Hash( "time", duration, "x", randomScale.x, "y", randomScale.y, "z", randomScale.z, "easetype", iEaseType, "looptype", iLoopType, "oncomplete", "OniTweenComplete", "oncompletetarget", thisGO, "oncompleteparams", cubeGO ) );
            } else {
                iTween.ScaleTo( cubeGO, iTween.Hash( "time", duration, "x", randomScale.x, "y", randomScale.y, "z", randomScale.z, "easetype", iEaseType, "looptype", iLoopType ) );
            }
        }
    break;
    case TweenEngine.GoKit:
        // ITWEEN
        if ( toggleColOut ) {
            if ( !callbackAdded && testType == TestType.Emit ) {
                callbackAdded = true;
                Go.to (cubeGO.transform,duration,new GoTweenConfig().materialColor(endCol)
                       .setIterations(goLoops,goLoopType)
                       .onComplete(delegate {
                    cubes.RemoveAt(cubes.IndexOf(cubeGO));
                    Destroy(cubeGO);
                    NewTween();
            }));
            } else {
                Go.to (cubeGO.transform,duration,new GoTweenConfig().materialColor(endCol).setIterations(goLoops,goLoopType));
            }
        }
        if ( togglePos ) {
            if ( !callbackAdded && testType == TestType.Emit ) {
                callbackAdded = true;
                Go.to(cubeGO.transform,duration,new GoTweenConfig().position(RandomToPosition(),true)
                      .setIterations(goLoops,goLoopType)
                      .onComplete(delegate {
                    cubes.RemoveAt(cubes.IndexOf(cubeGO));
                    Destroy(cubeGO);
                    NewTween();
                }));
            } else {
                Go.to(cubeGO.transform,duration,new GoTweenConfig().position(RandomToPosition(),true).setIterations(goLoops,goLoopType));
            }
        }
        if ( toggleRot ) {
            if ( !callbackAdded && testType == TestType.Emit ) {
                callbackAdded = true;
                Go.to(cubeGO.transform,duration,new GoTweenConfig().rotation(RandomRotation(),true)
                      .setIterations(goLoops,goLoopType)
                      .onComplete(delegate {
                    cubes.RemoveAt(cubes.IndexOf(cubeGO));
                    Destroy(cubeGO);
                    NewTween();
                }));
            } else {
                Go.to(cubeGO.transform,duration,new GoTweenConfig().rotation(RandomRotation(),true).setIterations(goLoops,goLoopType));
            }
        }
        if ( toggleScale ) {
            if ( !callbackAdded && testType == TestType.Emit ) {
                callbackAdded = true;
                Go.to(cubeGO.transform,duration,new GoTweenConfig()
                      .scale(RandomScale(),true)
                      .setIterations(goLoops,goLoopType)
                      .onComplete(delegate {
                    cubes.RemoveAt(cubes.IndexOf(cubeGO));
                    Destroy(cubeGO);
                    NewTween();
                }));
            } else {
                Go.to(cubeGO.transform,duration,new GoTweenConfig().scale(RandomScale(),true).setIterations(goLoops,goLoopType));
            }
        }
        break;
    }
}

/// <summary>
/// Returns a random initial position.
/// </summary>
private Vector3 RandomFromPosition()
{
    Vector2 r = UnityEngine.Random.insideUnitCircle * 30;
    Vector3 v = new Vector3( r.x, r.y, UnityEngine.Random.Range( -10, -30 ) );

    return v;
}

/// <summary>
/// Returns a random position to tween to.
/// </summary>
private Vector3 RandomToPosition()
{
    Vector3 v = UnityEngine.Random.onUnitSphere * 40;
    if ( v.z > 0 )      v.z = -v.z;

    return v;
}

/// <summary>
/// Returns a random rotation.
/// </summary>
private Quaternion RandomRotation()
{
    return UnityEngine.Random.rotation;
}

/// <summary>
/// Returns a random scale.
/// </summary>
private Vector3 RandomScale()
{
    float rand = UnityEngine.Random.Range( 2f, 4f );
    return new Vector3( rand, rand, rand );
}

/// <summary>
/// Returns a random color.
/// </summary>
private Color RandomColor()
{
    return new Color( UnityEngine.Random.Range( 0.1f, 0.8f ), UnityEngine.Random.Range( 0.1f, 0.8f ), UnityEngine.Random.Range( 0.1f, 0.8f ), 1 );
}

/// <summary>
/// Gets the total number of toggles that are selected.
/// </summary>
private int GetTotToggles()
{
    int res = 0;
    if ( toggleColOut ) ++res;
    if ( togglePos )    ++res;
    if ( toggleRot )    ++res;
    if ( toggleScale )  ++res;
    return res;
}

/// <summary>
/// Plays current tweens.
/// </summary>
private void Play()
{
    if (twEngine == TweenEngine.HOTween)
        HOTween.Play ();
    else if (twEngine == TweenEngine.iTween)
        iTween.Resume ();
    else {
        //Go.
    }
}

/// <summary>
/// Pauses current tweens.
/// </summary>
private void Pause()
{
    if (twEngine == TweenEngine.HOTween) {
        HOTween.Pause ();
    } else if (twEngine == TweenEngine.iTween) {
        iTween.Pause (); // Warning: doesn't work if test type is Emit and there are too many cubes.
    }
    else {

    }
}

// ===================================================================================
// HANDLERS --------------------------------------------------------------------------

/// <summary>
/// HOTween onComplete callback.
/// </summary>
private void OnHOTweenComplete( TweenEvent e )
{
    // Destroy the completed cube and create a new tweened one.
    GameObject cubeGO = (GameObject)( e.parms[0] );
    Destroy( cubeGO );
    cubes.RemoveAt( cubes.IndexOf( cubeGO ) );
    NewTween();
}

/// <summary>
/// iTween onComplete callback.
/// </summary>
private void OniTweenComplete( GameObject p_cubeGO )
{
    // Destroy the completed cube and create a new tweened one.
    Destroy( p_cubeGO );
    cubes.RemoveAt( cubes.IndexOf( p_cubeGO ) );
    NewTween();
}
private void GoTweenPlay(){

}
private void GoTweenPause(){

}

}

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1