Anims.play throwing error on soft refresh

ok, I’ve been stuck on this for days… the code is a mess now because of all the stuff I’ve been trying.

Here’s what happens - everything works great when I do a hard refresh of the page. When I do a soft refresh, I get the following error when it hits the .play() command.
(using regular phaser.js instead of the phaser.min.js file temporarily )

fishobject.anims.play(arr[index].name+‘swim’,true);
Uncaught TypeError: animationFrame is undefined
phaser-arcade-physics.js:104554:9

=================== CODE ========================
import { handleStartGame, saveDecor } from “./serverContact.js”

var scene = new Phaser.Scene(“game”);
var allLoaded = false;
var decorLoaded = false;
var fisharray = [];
var fishobjects = [];
var decorArray = [];
var decorobjects = [];
var aquariumid =document.getElementsByName(‘aquariumid’)[0].content;
//var newfish = { name: ‘’, url: ‘’, width: 0, height: 0, frames: 0, targetx: 0, targety: 0 };

scene.preload = function() {
this.load.image(‘background’,‘http://images.powerpets.com/image/aquarium/bg-oddcity.png’);
//name,xpos,ypos,image,locked, width,height,frames
// addDecor(‘threetowercastle’,200,200,‘threetowercastle.png’,0,161,238,1);
// addDecor(‘210344935’,572,391,‘woodenarch.png’,0,141,87,1)
// addFish(‘duskyshark’,‘duskyshark.png’,145,76,20);

async function loadAQData() {
	let response = await handleStartGame(scene,aquariumid)

    return response;
};


loadAQData().then(data => {
	loadFish(data).then(allLoaded=true);
	loadDecor(data).then(decorLoaded=true);
});

let loadDecor = async function(data) {
	let totdecor=data["account"];

// totdecor=2;
console.log(“Total Decor:”+totdecor);
for (let i=0;i<totdecor;i++) {
if (typeof data[“aid”+i] !== ‘undefined’) {
// aid, axp, ayp, adp, aimg, locked, awidth, aheight, aframes
console.log(‘decor’+data[“aid”+i]+", “+data[“axp”+i]+”, “+data[“ayp”+i]+”, “+data[“aimg”+i]+”, “+data[“locked”+i]+”, “+data[“awidth”+i]+”, “+data[“aheight”+i]+”, "+data[“aframes”+i]);
addDecor(‘decor’+data[“aid”+i],data[“axp”+i],data[“ayp”+i],data[“aimg”+i],data[“locked”+i],data[“awidth”+i],data[“aheight”+i],data[“aframes”+i],data[“adp”+i]);
}
}
decorArray.forEach(loadSprites);
console.log(‘Decor Loaded’);
// decorLoaded=true;
return
}

let loadFish = async function(data) {
	// time to load my fish 
	let totfish=data["ficount"];
	console.log("Total fish:"+totfish);

// totfish=1
for (let i=0;i<totfish;i++) {
if (typeof data[“ftype”+i] !== ‘undefined’) {
// console.log(i+“Adding " + data[“ftype”+i]+”,"+data[“fimg”+i]+","+data[“fwidth”+i]+","+data[“fheight”+i]+","+data[“fframes”+i]);
addFish(data[“ftype”+i]+i,data[“fimg”+i],data[“fwidth”+i],data[“fheight”+i],data[“fframes”+i],data[“fspeed”+i],data[“fhealth”+i],data[“ffeed”+i]);
}
}
fisharray.forEach(await loadSprites);
console.log(‘Fish Loaded’);
return
}

function addFish(name,image,width,height,frames,speed,health,feed) {
	var newfish = { name: '', url: '', x: 300, y: 200, width: 0, height: 0, frames: 0, targetx: 0, targety: 0, speed: 10, health: 0, feed: 0 };
	newfish.name=name.replace(/\s/g, '');
	newfish.url='http://images.powerpets.com/image/aquarium/sprites/'+image;
	newfish.width=Number(width); newfish.height=Number(height); newfish.frames=Number(frames);
	newfish.speed=Number(speed); newfish.health=Number(health); newfish.feed=feed; 
	console.log("ADDED " + newfish.name+","+newfish.url+","+newfish.width+","+newfish.height+","+newfish.frames+","+newfish.speed)
	fisharray.push(newfish);
}

function addDecor(name,xpos,ypos,image,locked, width,height,frames,depth) {
	var newdecor = { name: '', url: '', locked: 0, x: 0, y: 0, width: 0, height: 0, frames: 0, depth: 0 }
	newdecor.name=name;
	newdecor.url='http://images.powerpets.com/image/aquarium/sprites/'+image+'?nocache='+ $.now();
	newdecor.depth=Number(depth); newdecor.locked=Number(locked); newdecor.x=Number(xpos); newdecor.y=Number(ypos); newdecor.width=Number(width); newdecor.height=Number(height); newdecor.frames=Number(frames);
	console.log("ADDED " + newdecor.name + "," + newdecor.url + "," + newdecor.locked + "," + newdecor.x + "," + newdecor.y + "," + newdecor.width + "," + newdecor.height + "," + newdecor.frames);
	decorArray.push(newdecor);
}

function loadSprites(item,index,arr) {
	scene.load.spritesheet(arr[index].name, arr[index].url, { frameWidth: arr[index].width, frameHeight: arr[index].height, endFrame: arr[index].frames });
}

};

scene.create = function() {
this.add.image(315,250,‘background’);
this.physics.world.setBounds(0,0,630,500);

function waitForFish() {
	if (allLoaded) {
		fisharray.forEach(loadFish);
	} else {
		setTimeout(waitForFish,500);
	}
}
function waitForDecor() {
	if (decorLoaded) {
		decorArray.forEach(animateDecor);
		console.log('loading decor now');
	} else {
		setTimeout(waitForDecor,500);
		console.log('waiting for decor');
	}
}

setTimeout(waitForFish,1000);

// setTimeout(waitForDecor,500);

// fisharray.forEach(animateFish);

function loadFish(item,index,arr) {
	var fishobject, target;
	fishobject = scene.physics.add.sprite(arr[index].x,arr[index].y,arr[index].name);
	target= new Phaser.Math.Vector2();
	scene.anims.create({
	    key: arr[index].name+'swim',
	    frames: scene.anims.generateFrameNumbers(arr[index].name, { start: 0, end: arr[index].frames-1 }),
	    frameRate: 10,
	    repeat: -1
	});	
	console.log('Playing sprite '+arr[index].name);
	fishobject.anims.play(arr[index].name+'swim',true);

	fishobject.targetx=target.x=Math.floor(Math.random()*1260);
	fishobject.targety=target.y=Math.floor(Math.random()*350)+50;
	fishobject.speed=arr[index].speed*10;
	if (target.x<fishobject.x) fishobject.setFlipX(true);

	scene.physics.moveToObject(fishobject, target, fishobject.speed);
	fishobjects.push(fishobject);
};


function animateDecor(item,index,arr) {
	var decorobject;

	console.log(arr[index].x+","+arr[index].y+","+arr[index].name+","+arr[index].frames);
	if (arr[index].frames==1) {
		decorobject = scene.add.image(arr[index].x,arr[index].y,arr[index].name); 
	} else {
		decorobject = scene.physics.add.sprite(arr[index].x,arr[index].y,arr[index].name);
		scene.anims.create({
		    key: arr[index].name+'animate',
		    frames: scene.anims.generateFrameNumbers(arr[index].name, { start: 0, end: arr[index].frames-1 }),
		    frameRate: 10,
		    repeat: -1
		});	
		decorobject.anims.play(arr[index].name+'animate',true);
	}

/* decorobject.setInteractive();
scene.input.setDraggable(decorobject);
decorobjects.push(decorobject);
*/ }

};

scene.update = function() {

scene.input.on('dragstart', function (pointer, gameObject) {

    gameObject.setTint(0xff0000);

});
scene.input.on('drag', function (pointer, gameObject, dragX, dragY) {

    gameObject.x = dragX;
    gameObject.y = dragY;

});
scene.input.on('dragend', async function (pointer, gameObject) {

    gameObject.clearTint();

    // save data to server here
	// await saveDecor(gameObject.name, gameObject.x,gameObject.y,gameObject.depth)
});


fishobjects.forEach(moveSprites);

function moveSprites(item,index,arr) {
	var target,newydiff,newy;

	var distance = Phaser.Math.Distance.Between(arr[index].x,arr[index].y,arr[index].targetx,arr[index].targety);
	target= new Phaser.Math.Vector2();
	if (arr[index].body.speed>0) {
		if (distance<4) {
			arr[index].body.reset(arr[index].targetx,arr[index].targety);
			arr[index].targetx=target.x=Math.floor(Math.random()*1260);
			newydiff=Math.floor(Math.random()*100)-50;
			newy=arr[index].y+newydiff;
			if (newy<20) newy=60;
			if (newy>400) newy=350;
			arr[index].targety=target.y=newy;
			if (target.x<arr[index].x) {
				arr[index].setFlipX(true);
			} else {
				arr[index].setFlipX(false);
			}
			scene.physics.moveToObject(arr[index], target, arr[index].speed);
		}
	}
};

}

const config = {
type: Phaser.AUTO,
width: 630,
height: 500,
backgroundcolor: “#FFFFFF”,
scene: scene,
physics: {
default: ‘arcade’,
arcade: {
debug: false
}
}, parent: ‘phaser-div’
};

const aquarium = new Phaser.Game(config);

I did a bit more testing. Network communications indicate that:
scene.load.spritesheet(arr[index].name, arr[index].url, { frameWidth: arr[index].width, frameHeight: arr[index].height, endFrame: arr[index].frames });

doesn’t seem to actually invoke a GET all the time. I’ll guess it’s trying to pull the images from browser cache and it’s not working. I tried to add a ?nocache to the file names, but that’s not working either.

Fish Loaded
Total Decor:0
Decor Loaded
Playing sprite BlueTang0


should be…
Fish Loaded
Total Decor:0
Decor Loaded
GEThttp://images.powerpets.com/image/aquarium/sprites/bluetang.png?nocache=1602960540469
GEThttp://images.powerpets.com/image/aquarium/sprites/yellowtang.png?nocache=1602960540470

Playing sprite BlueTang0

Does anyone have a suggestion? It seems to work fine if I hardcode the asset list instead of loading it from the server. However I prefer not to hardcode 400+ items into the preloader when I may only need 20 or 30 of those.

I can’t follow the code completely but I don’t think any assets are added/queued by the end of preload(). You can verify this by adding

console.assert(this.load.list.size > 0, 'load list should not be empty');

to the end of preload().

For dynamic loading you might be better off adding animations via FILE_COMPLETE or FILE_KEY_COMPLETE.

Thanks Samme!

It’s not the most elegant solution, but managed to resolve it by adding this in the Create section:

		if (decorLoaded && allLoaded) scene.load.start();

For some reason, the Preload doesn’t always fire the load.start() - even though the docs say it should…

The LoaderPlugin starts loading automatically only if assets are queued during preload(). Async calls will complete after that, too late.