Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

HOTween: a fast and powerful Unity tween engine

Discussion in 'Assets and Asset Store' started by Demigiant, Jan 7, 2012.

  1. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Thanks petey for posting those easings!

    And by the way, I was superbusy finishing a game for The Edge contest (Goscurry), but now I'll get back to the punch and shake matter :)
     
  2. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,771
    No worries!
    Hey Goscurry looks pretty cool! I dig the little avatar you get :)
     
  3. Trithilon

    Trithilon

    Joined:
    Aug 2, 2012
    Posts:
    30
    Hello,
    Is it possible to use multiple tweens on a single object property?
    Say, I am tweening an object forward and now I want it to also move upwards dynamically.

    HOTween.To(Camera.main.transform,3.5f,new TweenParms()
    .Prop("position", new Vector3(0, 0, 50), true)
    .Loops(-1, LoopType.Yoyo)
    .Prop("rotation", new Vector3(1024,0,0),true) // This gets ignored
    .Prop("rotation", new Vector3(0,0,1024),true) // This gets tweened
    );

    I tried using two props side by side, I expected them to stack. Why won't that happen? Only the last prop using that particular fieldname (rotation) was considered.

    So... basically, is it suited for stacking multiple tweens together for example, running and jumping?

    Regards.
     
  4. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,771
  5. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Thanks Petey! And just so you know, the avatar that looks like Jesus is not Jesus: it's a pixel version of myself (I will have to put a disclaimer, because lots of people are asking "why Jesus in the avatars!" :D)

    Trithilon, follow what Petey said, if you want to animate each axis separately (and remember to include the Holoville.HOTween.Plugins package if you're using it), like:
    Code (csharp):
    1.  
    2. ...
    3. .Prop("rotation", new PlugVector3X(1024),true)
    4. ...
    5.  
     
  6. Trithilon

    Trithilon

    Joined:
    Aug 2, 2012
    Posts:
    30
    Oh thank you!
    I think this can be made to work for that I want.

    But... isn't it possible for HoTween to interpolate between all the tweens and do the stacking?

    Say... I have a 5 second Diagonal movement. And I want to start tweening 1 unit per second upwards at 2s duration - could that be done dynamically (I know, I can always use a Dummy Vector3 and do the Lerping myself)?
    Or for all you know... I could make a tween which stacks to increase my speed everytime I press forward.

    Also... I'll ask two quick questions while I am out.
    Can you :
    1: Make a sequence of sequences?
    2: Have two Sequences affect the same object?
     
  7. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    No, tweens can't be stacked like you're saying. But you can change (or even tween) a Tweener/Sequence's own timeScale even while said Tweener/Sequence is running, so you could achieve a speed up/down effect :)

    About the other answers:
    1. Sure, you can make Sequences of Sequences
    2. You can affect same object with more Sequences/Tweeners. Though, an identical property of the same instance can't be tweened at the same time (the last created one will overwrite the previous one)
     
  8. Trithilon

    Trithilon

    Joined:
    Aug 2, 2012
    Posts:
    30
    Thank you... I am thinking of creating a helper function which will try touse a Dummy Vector 3 and could update the Tween in realtime with fresh values once it accepts a tweening job. Any idea of how to access the current tweening values or how to modify a running tween on the fly?

    Apart from this...
    I am trying to understand if the default behaviour of HOtween autokilling Tweens on complete is REALLY needed...

    https://dl.dropboxusercontent.com/u/9030688/Works/Works.html

    Once you scrub to 8 sec, the tween gets killed, but its still there. But if I "Clear" it, it goes away (atleast the knob on the slider does).
    What is the difference between them?

    To give you an idea of what I would be doing... I am trying to make a movement system for a runner game (which will also have time reversal mechanic). I would be maintaining a pool of points to generate a path which will be dynamically generated in my game and I will be tweening my character from point to point to move forward or to switch between lanes (each lane will be a path).

    So... essentially I would be dynamically adding a lot of tweeners to my main sequence and dynamically. And the game by design could be an endless runner so Garbage collection is something I would like to avoid.

    The reason I am going through the pain of making a Tween based movement rather than the conventional translation based movement is because of the ability to scrub through time and have prefixed points of interests and specific events movement paths.
     
  9. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Hi! :)

    I'll start with autoKill. HOTween uses a single object to update all tweens, which contains a list of all existing tweens. AutoKill is thus needed, because it automatically removes a tween from said list, so the list doesn't grow up to contain useless stuff.
    In your example, you still see some data because killing a tween means removing it from the main HOTween update list. But the "data" for it is still kept if you created it as a reference, so until you set myTween = null (which I suppose is what you do with your Clear method) it will still exist, thought it won't be able to be used anymore.

    Changing tweens endValues while they're running instead, is not possible. What you could do, is Clear your Sequence (to re-use it and save at least some GC, though there will still be some), then reassign new tweens with the new endValues, and immediately GoTo the "current" position, so nothing appears to have changed.
    All in all, since you're changing end values a lot, I would still avoid using HOTween, and develop a custom system just for that. You could check out HOTween path algorithms (inside the PlugVector3Path class) and re-use them to create your own interchangeable path system. That way, you could simply recalculate the path at every update, and if you change it everything will behave accordingly. Then, implementing a custom GoTo method would be quite easy starting from HOTween's path algorithms, since they implement something like that already.
     
  10. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Hey there,

    can i use the Hotween Visual Editor for tweening an object directly to another object? Like drag and drop Object A and then drag and drop Object B, for now i am I'm just writing the exact Transform-Coordinates but that is kind of...yeah impractical. For example: when the position of Object B is changing the whole tween is useless.
     
  11. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Hey,

    sorry but no. Tween end values can't be changed (once a tween has started). If you want to just move something in a direction which might be changing at any time, I would recommend moving the object yourself using Update or something like that, instead than using a tween.
     
  12. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Mhm, allright. Never mind, i'll think of something. Your tool is still great :p :D
     
  13. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
  14. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Hey there. So I am building a Menu-System with nGUI. The Logic is made with PlayMaker. So there is a PauseButton on the Screen and when it hits a HOTween-Action is played (by PlayMaker), which moves the GUI-Elements (Movement-Buttons) out the screen and shows the PauseMenu.
    The thing is: when the PauseButton is hit, the TimeScale is set to 0. Will that effect the tweenings? Will they also stop? If so: is there a way aroung that?
     
  15. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Hi Mayhem.

    When you set a tween with HOTween, you can use the TimeScaleIndependent UpdateType, which will ignore Unity's timeScale completely, even if set to 0.
     
  16. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    I can do this in the VisualEditor, too, right?
     
  17. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Yes, using the Update Type dropdown :)
     
  18. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Great! Thank you! :D
     
  19. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    And another one :D

    So currently I'm working on the AI and I want that my enemy is just patroling before chasing the Player. So what I want is that the enemy changes his position by an certain amount. So I'm tweening (with the Visual Editor) the Transform of the Enemy and there I'm tweening the "Local Position".
    The PluginType is set to PlugVector3X and it is set to Relative so: "Tween BY" and I'm tweening it by the value of "5" so it's wallking 5 to the right

    I also did another Tween with the same settings, just changed the Value from "5" to "-5" in order to tween the enemy to the left.

    So I'm doing the Logic with PlayMaker and play the Tweens via the ID. And it's working, which is great. There is only one thing that bothers me:

    The Enemy is moving right and left. Fine, then the player comes up in the Range of the Enemy and the Enemy is starting to chase the Player as it is intended. When the Player is out of Range, the Enemy goes way back to it's first original position when the game was started and moves from right to left. But he should move from right to left from that certain position he lost the player.
    Does that make sense or is it unclear what I mean? (Sorry, if it's not clear enough. Not a native speaker :/ )

    I tried it with iTween Move By and there it worked like it should....but yeah...I don't want to use iTween :D
     
  20. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    The first time you create a "tween by", the relative coordinates are forcefully converted to unrelative ones :p So if you play it again it will go back to where it started. The solution would be to change the "position" of the enemy when chasing the player (while instead I assume you're changing its localPosition), and leave the "localPosition" to make him move left/right :)
     
  21. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Thanks for the fast reply!
    Yeah, I tweened the localPosition, but now I tried the "position" and it's still the same result :/
     
  22. srmojuze

    srmojuze

    Joined:
    Mar 18, 2013
    Posts:
    127
    Bought a few weeks back. Very nice, brings back memories of Flash back in the day. Tween, tween, tween, tween, tween LOL.
     
  23. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    @Mayhem: but did you leave "localPosition" for the right/left movement? If yes, there must be something that moves the enemy's localPosition somehow. Try to check the localPosition of the enemy when it moves. If it somehow changes, then something's wrong.

    @srmojuze: LOL I agree :D
     
  24. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Now I'm confused, I thought I shouldn't tween the localPosition and instead the position :D ?

    I made some Screenshots.
    Here is the Tween-Setup:



    And here is the PM-Action:




    Edit:

    I already changed the PluginVector Type from "PlugVector3" to "PlugVector3X" in the ENEMYRIGHT Tween. That wasn't the problem
     
  25. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Aha no, sorry for the confusion :D ENEMYLEFT and ENEMYRIGHT should tween localPosition. Instead what should use "position" is the enemy movement when chasing the player.
     
  26. WingedS

    WingedS

    Joined:
    May 8, 2013
    Posts:
    19
    This is a great plugin. I've been messing around with it, it's great.

    How do you use OnComplete with params? I'm a bit stuck here.

    Ex:

    Code (csharp):
    1.  
    2. string[] tempParams =  new string[1];
    3. tempParams[0] = "Hello";
    4. Hotween.To(...OnComplete(MyFunction, tempParams));
    5.  
    6. void MyFunction(string a){}
    7.  
    I'm not sure how to use the params and would gladly appreciate it if someone can help me. Thanks.
     
    Last edited: May 11, 2013
  27. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Hi WingedS, glad you're liking it :)

    About params, the OnComplete callback must accept a parameter of type TweenEvent, which will contain a property called "parms" that will represent an array of all the parameters you passed to OnComplete (more on it here). For example:

    Code (csharp):
    1.  
    2. HOTween.To(...
    3.   .OnComplete(MyFunction, "someString", 21)
    4. );
    5. ...
    6. void MyFunction(TweenEvent e)
    7. {
    8.   Debug.Log(e.parms[0]); // outputs "someString"
    9.   Debug.Log(e.parms[1]); // outputs 21
    10. }
    11.  
     
  28. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    What. Chasing is working completely fine without tweens. I was talking about the patroulling all the time.

    Patrol (Tween with localPosition) - Chasing (no Tweens) - back to Patrol with Tweens.

    But he doesn't patrol from the point he lost the Player, the Enemy/GameObject disappears from that spot and "beams" to its original startpoint and patrols there again. The Patroling itself works fine with tweens, it's the Replaying at the startpoint which makes trouble.
     
  29. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Yup, but the problem is that, tweens or not, the chasing is moving the localPosition of the enemy. So when you replay the same tween its initial localPosition won't work anymore :p
     
  30. WingedS

    WingedS

    Joined:
    May 8, 2013
    Posts:
    19
    Thanks Izitmee, now I understand how to use the params!
     
  31. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Hm, yeah I understand that, but I don't understand that it becomes again the initial localPosition, in particular because it works in iTween.
    I mean, let's say:

    Enemy is at Startposition 0/0/0 (X/Y/Z).

    The Tween moves him by 5 to the right and 5 to the left, so he goes to 5/0/0 and then back to 0/0/0.

    The Player comes along and the enemy follows him. Now his position is not anymore 0/0/0 but let's say 25/0/0. At this point he loses the player and goes back to his Patrol-Routine. So he had to go from 25/0/0 to 30/0/0 and then back to 25/0/0.

    I thought when I set the Tween to "Relative" it will take the actual localPosition of the GameObject ingame and move it by the Value I want to.

    I was just curious why it worked in iTweens but not in HOTween and thought this was a mistake of mine with some wrong settings.
     
  32. Bitawu

    Bitawu

    Joined:
    May 11, 2013
    Posts:
    14
    Hello Izitmee,

    First off thank you for making such a wonderful tool! I've been playing around with it and have been really enjoying it.

    I did recently stumble upon a slight problem building sequences with a delay property in TweenParms. When I build/play the sequence without delays it runs fine, but if I add any sort of delay it seems tweeners begin to overlap and become erratic. For example, making the first phase of a two step movement tween have the same delay as its duration causes movement from origin to the first step, then instant teleport to the origin, and finally a tween from origin to step 2.

    Here's an example of how I am building my sequences:

    Code (csharp):
    1. for (int i = 0; i < wpList.Count; i++){
    2. wpSequence.Append(HOTween.To(followerTransform, duration, new TweenParms().Prop("position", wpList[i].transform.position).Delay(wpList[i].wpDelay).OnComplete(OnReachedNextWaypoint)));
    3. }
    Am I missing something here? I'd just like the delay to pause between tweens if need be.

    Thanks for any direction you can give me here!
     
  33. soundwav_

    soundwav_

    Joined:
    Apr 23, 2013
    Posts:
    12
    Hello, I'm trying to use HOTween to animate the gameObject.renderer.material.mainTextureOffset.y property.

    From my understanding, my code should look something like this:
    Code (csharp):
    1. TweenParms parms = new TweenParms().Prop("y", 1f, true).Loops(3, LoopType.Incremental).Ease(EaseType.Linear).OnComplete(tweenComplete);
    2. HOTween.To(gameObject.renderer.material.mainTextureOffset, 1.8f, parms );
    I don't get any warnings, but nothing is happening.
    EDIT: The callback is being called, but there is no animation.

    I was able to animate this property using iTween, but I want to do some speed comparisons and see which gives the best results.

    FINAL EDIT:
    I shouldn't have been so quick to post :)
    I got it working like this:
    Code (csharp):
    1. TweenParms parms = new TweenParms().Prop("mainTextureOffset", new Vector2(0, 1f), true).Loops(3, LoopType.Incremental).Ease(EaseType.Linear).OnComplete(tweenComplete);
    2.         HOTween.To(gameObject.renderer.material, 0.5f, parms );
    And for those wondering, it does seem that HOTween has fewer hiccups on those lines of code than iTween (using iPhone4), although I still get some rare hiccups sometimes. I gotta figure out what causes them.

    Thanks for making this plugin!
     
    Last edited: May 12, 2013
  34. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    @soundwav_: glad you found the solution :) Vector values in Unity's classes are created as structs, and as such their x/y/z/w values can't be directly changed nor tweened, and you have to assign a whole new vector instead (JS "tricks" you into thinking you can actually modify those values directly, but in reality does a whole vector re-assignment in the background).

    @HendoTKO: glad you like it :) Delays don't work well in Sequences. To have a pause between each of the Sequence tweens, you should simply use AppendInterval

    @Mayhem: the first time you create a relative tween, the coordinates are created as relative but converted to absolute. That's why the first time it works correctly, but if you move the localPosition after playing it once it doesn't anymore. iTween evidently uses a different setup :)
     
  35. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Yeah, ok, I understand that. So what would be now the solution for the desired behaviour with HOTween :) ?

    And by the way: Thanks for the support ;)
     
  36. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    You're welcome ;) Well solution might be to have a gameObject container for the enemy. Let's call it ContGO for this example. You move ContGO when chasing the player (so enemy's localPosition doesn't change), and instead move enemy's localPosition when going left/right, so it will work everywhere.
     
  37. BTStone

    BTStone

    Joined:
    Mar 10, 2012
    Posts:
    1,418
    Do you mean that I should make an Empty GameObject and Make the Enemy Object a Child of that?
     
  38. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Yup. Then move the empty GameObject's position when chasing, and the Enemy Object's localPosition when patrolling left/right.
     
  39. Bitawu

    Bitawu

    Joined:
    May 11, 2013
    Posts:
    14
    Ahhhh thank you! It works like a charm now. I had a feeling I was doing something wrong; adding the delays to the sequence with the tween made sense in my head, you know?

    Thanks again for the unbelievably fast support and this awesome (and FREE?! HOW?!?!) tool!
     
  40. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Actually I thought about throwing a warning to prevent users from adding delays and loops into Sequences. But then I realized that, while they don't work correctly, they still work in a curious way. And you can play with it and create weird tweens :p

    Ahahah and HOTween is obviously free: I mean, if Jack Doyle's TweenMax/Lite (which I consider the best tween engine ever, and used a lot) is free, nothing in the genre can behave differently :D
     
  41. Danz0r77

    Danz0r77

    Joined:
    Mar 19, 2013
    Posts:
    20
    Hi Izitmee,

    I've just started using HOTween and I'm struggling with something that I expect should be fairly simple. Hopefully you can explain what might be wrong.

    I made a post here:
    http://forum.unity3d.com/threads/18...tiple-tweens-one-object?p=1245209#post1245209

    I then saw, reading through this thread, that I should use PlugVector3Y and X instead but when I do that it isn't moving relative anymore. The objects move to the world coordinates.

    I'm creating a sequence like this to make the objects move up 1 unit and back down but each object moves to world Y coordinate 1:

    Code (csharp):
    1. var mySequence = new Sequence(new SequenceParms().Loops(-1,LoopType.Yoyo));
    2.     mySequence.Append(HOTween.To(transform, 1, new TweenParms().Prop("position",PlugVector3Y(1),true).Ease(EaseType.Linear)));
    3.     mySequence.Play();
    What am I getting wrong?

    Thanks
     
  42. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Hi Danz0r77,

    if you use a plugin, the "relative" parameter should be placed inside it. So, instead of:
    Code (csharp):
    1.  
    2. ...Prop("position",PlugVector3Y(1),true)...
    3.  
    you should write
    Code (csharp):
    1.  
    2. ...Prop("position",PlugVector3Y(1, true))...
    3.  
     
  43. Danz0r77

    Danz0r77

    Joined:
    Mar 19, 2013
    Posts:
    20
    Thanks for that - knew it would be something simple :)

    So, to gain the movement effect I would like.. I.E. Objects move left 10 units over 5 seconds, while also moving up / down over 1 second - I have the following:

    Code (csharp):
    1. var mySequence = new Sequence(new SequenceParms().Loops(-1,LoopType.Yoyo));
    2.     mySequence.Append(HOTween.To(transform, 5, new TweenParms().Prop("position", new PlugVector3X(-10,true)).Ease(EaseType.Linear)));
    3.     var mySequence2 = new Sequence(new SequenceParms().Loops(-1,LoopType.Yoyo));
    4.     mySequence2.Append(HOTween.To(transform, 1, new TweenParms().Prop("position",PlugVector3Y(1,true)).Ease(EaseType.Linear)));
    5.     mySequence.Play();
    6.     mySequence2.Play();
    I don't think this is the best way is it? Would it be better to run a callback on complete and just do the reverse motion? Or is there a better way? I'm new to tweens altogether :-/
     
  44. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    I'm not sure why you need the reverse motion and the callback. If you're trying to achieve a loop, then surely the Loops method-parameter is the way to go, but maybe I misunderstood something :p

    Anyway, there's no need to use Sequences in this case, since you just have a single separate tween per Sequence. So you could just replace all the code above with this, and assign the loop to the Tween instead than to the Sequence:
    Code (csharp):
    1.  
    2. HOTween.To(transform, 5, new TweenParms().Prop("position", new PlugVector3X(-10,true)).Ease(EaseType.Linear).Loops(-1,LoopType.Yoyo));
    3. HOTween.To(transform, 1, new TweenParms().Prop("position",PlugVector3Y(1,true)).Ease(EaseType.Linear).Loops(-1,LoopType.Yoyo));
    4.  
     
  45. Danz0r77

    Danz0r77

    Joined:
    Mar 19, 2013
    Posts:
    20
    Ok I see what you mean. Makes sense now.

    Thanks for the help :)

    Also, one final question.. is it possible to add the component to a Prefab? When I do this I can't add any tweens as the popup box disappears as soon as I move the mouse. Is this how it should be?
     
  46. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    You mean the HOTween Visual Editor component? It's definitely possible. Are you sure you're not using the HOTweenManager (which doesn't work with prefabs) directly instead?
     
  47. Danz0r77

    Danz0r77

    Joined:
    Mar 19, 2013
    Posts:
    20
    It's the one where, when I click on a prefab in the Project view, then go to Add Component > HOTween > HOTween Component.

    It works fine on a game object in the scene heirarchy but not on a prefab in Project View.
     
  48. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Ouch, I just tested it and you're right - will have to fix that. In the meantime, you can easily do it anyway by:

    - dragging your prefab to the Hierarchy
    - assigning/changing the HOTweenComponent properties
    - applying the changes to the prefab

    This way they will be stored inside the prefab and work in runtime. What's not working is not the tween part, but the GUI part :p
     
  49. mochatony

    mochatony

    Joined:
    Jul 24, 2012
    Posts:
    14
    Hi

    Would like to know is there a recommended way of moving a batch of game objects (50-100) at the time, as I am currently using for loop for moving each objects. I found it is a bit laggy, when I run shuriken particle system on top of it with my 3gs.

    HOTween.To(obj.transform, 1.0f, parms);

    Btw, thank you so much for creating this tween library.
     
  50. Demigiant

    Demigiant

    Joined:
    Jan 27, 2011
    Posts:
    3,239
    Hi :)

    If they all move in a similar amount and you want to use less resources, you could create a single tween and use the OnUpdate callback to update the others? Tell me more of what you're trying to do, and I might think of an alternative