Notifications
Clear all

[Closed] How do you run a script on each frame of an animation

Hi, I am fairly new with max (been using it for about 6 months) and i just started playing with maxscript. I am making an animation of a m2 machine gun firing. You can see what i have so far at this link. www.jlasante.com/m2firing3.avi I have written a code that turns the bullets invisible after they pass through the center of the gun($BulletCenterPoint.pos.x). If i run the script manually it works and will turn any bullets that have gone through the center of the gun invisible. What I need now is to have this run once per frame so it can check to see if it needs to be invisible or not. This is the problem, I have no idea how to do this. Thanks ahead of time to anyone who can help.

bullet = $bullet01
  for i = 1 to 103 do
  (
  	nameString = "bullet"
  	p = i as string
  	if i < 10 then
  	(
  		append nameString "0"
  		append nameString p
  		--print nameString	
  	)
  	if i >= 10 then
  	(
  		append nameString p
  		--print nameString
  	)
  	for o in geometry do 
  	(
  		--print matchPattern (o.name as string) pattern:"bullet"
  		if matchPattern (o.name as string) pattern:nameString then
  		(
  		bullet = o
  		print bullet
  		)
  	)	   
  	if bullet.pos.x > $BulletCenterPoint.pos.x then
  	(
  		bullet.visibility = off
  		print bullet.visibility
  	)
  	if bullet.pos.x <= $BulletCenterPoint.pos.x then
  	(
  		bullet.visibility = on
  		print bullet.visibility
  		print "about to exit"
  		exit 
  	)
  )
  print "done"
10 Replies

Well, two possibilities would be to either do this as a baked animation script where you process your range of animation and as the script is calculating the visibility being on or off it actually records keys to that effect. You could pretty much do that by using the “animate on” command before your loop starts going and it’ll record keys for the on off entries. Alternatively you could use the script as an expression controller on the bullet object itself via the trackview but if you’re using hundreds of bullets it might be more hassle to manage the controllers if you decide to add more objects later on.

Out of those two ideas, the baked animation sounds like the best idea since there are 100 bullets, but I have no idea how to do that. any help would be great

Well, you’re pretty much doing it already since the loop you’ve got running is setting the key values – all you need to do is use the “animate on” command before your for i loop starts – max will autokey whatever animation gets done over the course of your loop. If you wanted to do something a bit more complicated (which isn’t necessary here) you could target the visibility controller of the object in the loop, add a key using maxscript and then set a value based on your distance test but again it’s not needed here.

I get the “animate on” from your explanation, but the way my bullets are animated are by using the reactor, then they get converted to key frames, so the animation is about 350 frames long and no animation really takes place during the course of the loop. On each frame i need to run this script, and i would prefer to not have to go through and do it myself. Is there a way i can automate that?

you want to look up ‘at time’ in the maxscript reference. This will let you execute your script at the given time(frame). By the way your script is far from optimized. Here is an optimized version for you:

(
 	for b in $bullet* do
 	(
 		if bullet.pos.x > $BulletCenterPoint.pos.x then
 		(
 			bullet.visibility = off
 			print bullet.visibility
 		)
 		else
 		(
 			bullet.visibility = on
 			print bullet.visibility
 		)
 	)
 )
    now just add the 'at time' and 'animate on' stuff as per the reference and you should be set

Thanks for all your help. i was able to finally do this. The baking the animation worked great. I ended up using this code to do it. Prob not the nicest way of doing it, but it got the job done so im happy. Once again thanks.

for j = 0 to 350 do
(
sliderTime = j
print sliderTime
bullet = $bullet01
bullet1Pos = $BulletCenterPoint.pos.x
print bullet1Pos
lastBulletPos = bullet1Pos
animate on
for i = 1 to 103 do
(
	nameString = "bullet"
	p = i as string
	if i < 10 then
	(
		append nameString "0"
		append nameString p
		--print nameString	
	)
	if i >= 10 then
	(
		append nameString p
		--print nameString
	)
	for o in geometry do 
	(
		--print matchPattern (o.name as string) pattern:"bullet"
		if matchPattern (o.name as string) pattern:nameString then
		(
		bullet = o
		print bullet
		)
	)	   
	if bullet.pos.x > $BulletCenterPoint.pos.x then
	(
		bullet.visibility = off
		print bullet.visibility
	)
	if bullet.pos.x <= $BulletCenterPoint.pos.x then
	(
		bullet.visibility = on
		print bullet.visibility
		print "about to exit"
		exit 
	)
)
print "done"
)
 PEN

A faster way is to use the at time context where you are not moving the slider and you don’t have to update the scene each time.


 for t = animationRange.start to animationRange.end do
 (
    animate on
    (
 	  at time t
 	  (
 		 --Do it all here.
 
 	  )
    )
 )
 
1 Reply
 JHN
(@jhn)
Joined: 11 months ago

Posts: 0

Be carefull though it will not work on everything… spline operations for example… :curious:

-Johan

 PEN

Please delete

 PEN

Please delete