Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by user-10716 (google) · Mar 25, 2011 at 01:18 PM · animationjavascriptarrayrandomfor-loop

Making an Array of Animations Play at Random With No Repeats

I have created a practice project to figure out how to get a random animation to play every time a button is clicked until all the animations have played with no animation playing twice. Ten animations are assigned to anims[] in the inspector. So far I have come up with this script:

var anims : AnimationClip[]; var randomAnims : AnimationClip[]; var order = new ArrayList(); var currentClip : AnimationClip; var chosenOne: int; var orderString = new ArrayList();

function OnGUI() { if (GUI.Button (Rect (105, 457, 100, 22), "Next")) { PlayAtRandom(); } }

function PlayAtRandom() { for (var i = anims.length - 1; i > 0; i--) { chosenOne = Random.Range(0,anims.length); var next = i.ToString(); var ind = orderString.IndexOf(next);

     if (ind < 0)
     {
         orderString.Add(next);
         order.Add(i);
         randomAnims[chosenOne] = anims[order[i]];
         currentClip = randomAnims[chosenOne];
         animation.Play(currentClip.name);
     }
 }

}

When I press play, and press the "Next" button, it generates an error saying "ArgumentOutOfRangeException: Index is less than 0 or more than or equal to the list count." Pointing to line 26 "randomAnims[chosenOne] = anims[order[i]];".

What am I doing wrong here? Thank you.

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

3 Replies

· Add your reply
  • Sort: 
avatar image
3

Answer by Statement · Mar 25, 2011 at 02:39 PM

If you're willing to rewrite your code, consider this example which uses shuffling and queues. It is still possible that two animations come after each other if the first order was a, c, b and the other order is b, a, c. However you can easily modify this code to know the last used animation and swap it for the one in the other end of the array. That way you're guaranteed to never have same animation appear twice in a row.

import System.Collections.Generic; var anims : AnimationClip[]; private var queue : Queue.<AnimationClip>;

// Added for comment discussion. private var lastAnim : AnimationClip;

function OnGUI() { if (GUI.Button (Rect (105, 457, 100, 22), "Next")) PlayNext(); }

function PlayNext() { if (queue == null || queue.Count == 0) CreateQueue();

 // Changed for comment discussion.
 lastAnim = queue.Dequeue();
 animation.Play(lastAnim.name);

}

function CreateQueue() { Shuffle(anims); Shuffle(anims); Shuffle(anims);

 // Added for comment discussion.
 // Swap the first and last if the first is the same as 
 // was used last animation.
 if (anims[0] == lastAnim)
 {
     var last = anims.Length - 1;
     var tmp = value[0];
     value[0] = value[last];
     value[last] = tmp;
 }

 queue = new Queue.&lt;AnimationClip&gt;(anims);

}

function Shuffle(value : AnimationClip[]) { for (var i = 0; i < value.Length; ++i) { var r = Random.Range(0, value.Length); var tmp = value[i]; value[i] = value[r]; value[r] = tmp; } }

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image user-10716 (google) · Mar 25, 2011 at 03:13 PM 0
Share

You said, "However you can easily modify this code to know the last used animation and swap it for the one in the other end of the array."

This is exactly what I need help on! How would I go about doing that?

avatar image Statement · Mar 25, 2011 at 05:16 PM 0
Share

Yes! I do! :) Just keep a private variable that you set each time you dequeue. Then in CreateQueue you can see if the first item in the array is the one (just before creating the queue). If it is, then swap it with the last item. See the shuffle function where I swap each item with a random item how to swap a value. You need a temp value (tmp) just like I did.

avatar image Statement · Mar 25, 2011 at 05:19 PM 0
Share

Check the updated code.

avatar image user-10716 (google) · Mar 25, 2011 at 06:20 PM 0
Share

This is very good. Thanks. I need to make sure that no animation that has played before ever plays again. So I guess the button text should change to "Stop" once it reaches the very end and when clicked, stops the current animation.

avatar image Statement · Mar 26, 2011 at 12:34 PM 0
Share

Yeah, you could just create a queue and run it until it's depleted. When its empty you've played all possible animations without any duplicates (assu$$anonymous$$g the array doesn't contain duplicates)

avatar image
-2

Answer by Meltdown · Mar 25, 2011 at 01:57 PM

Change the line of code that reads...

chosenOne = Random.Range(0,anims.length);

to

chosenOne = Random.Range(0,anims.length - 1);

You are trying to get a random animation, but since Random.Range takes a 0 based value, you need to put in the -1, so it will make sure you always getting a range within the bounds of the array.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Statement · Mar 25, 2011 at 02:09 PM 0
Share

Actually, Random.Range returns a random integer number between $$anonymous$$ [inclusive] and max [exclusive]. See http://unity3d.com/support/documentation/ScriptReference/Random.Range.html I was wrong about this for a long time.

avatar image
0

Answer by Statement · Mar 25, 2011 at 02:19 PM

randomAnims[chosenOne] = anims[order[i]];

You must have arrays of inconsistent length.

You're using an index based of the length of anims but it's unclear if order is at least as long as anims, and if any value in order is less than anims.length. Finally, your randomAnims also must be at least the size of anims. Are they?

Since you seem to be adding items to order procedurally, order.Add(i);, then try to index into it order[i], and i starts as the highest index, this looks like the place you're getting errors. Consider this with literal values:

order.Add(30);
randomAnims[chosenOne] = anims[   order[30]   ];

order only contains one item in the first iteration still you're trying to access the last...

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

No one has followed this question yet.

Related Questions

"For"-Loop only works for final element in array 1 Answer

Using arrays to randomly select an object 0 Answers

(20,57): BCE0022: Cannot convert 'EnemyAI[]' to 'EnemyAI'. 1 Answer

Simple array an spawning question 6 Answers

Tower defense, turret aiming wrong. 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges