Automatic Isometric Depth Sorting and Collisions Help

I’ve actually got 2 problems, but one is likely an easier fix than the other…

I have what I was hoping was going to be a script to help make depth sorting easier, which is supposed to update the unit’s depth when in motion, as follows:

var tileWidth = 128;
var tileHeight = 64;

//TILEMAP ARRAY EXAMPLE
levelData = 
[[0,0,0,0,0,0],
[0,1,8,8,7,0],
[0,2,9,9,6,0],
[0,2,9,9,6,0],
[0,3,4,4,5,0],
[0,0,0,0,0,0]];

//METRUS GAME OBJECT
class Metrus extends Phaser.Physics.Arcade.Sprite {

constructor(scene, x, y, motion, direction, distance, id, tileX, tileY) {
    super(scene, x, y, 'metrustotalsprite', direction.offset, id, tileX, tileY);

 	this.id = id;
	this.name = id;
    this.startX = x;
    this.startY = y;
	this.tileX = tileX;
	this.tileY = tileY;
    this.distance = distance;
    this.direction = direction;
	this.motion = motion;
	this.speed = 0.1;
	const tileHeightHalf = tileHeight / 2;
	this.depth = (tileY + tileX) * tileHeightHalf + 65;
	this.scene = scene;

	unitSprite = this.scene.matter.add.gameObject(this, { shape: 'circle', circleRadius: 15} );	
	unitSprite.setCollisionCategory(groundunits);
	unitSprite.setCollidesWith([ground, groundunits]);
	unitSprite.ignoreGravity = true;
	unitSprite.displayWidth = 30;
	unitSprite.displayHeight = 30;
	unitSprite.scale = 0.4;
	var circle = new Phaser.Geom.Circle(150, 150, 40);
	unitSprite.setInteractive(circle, Phaser.Geom.Circle.Contains);

    }

update() {
	
	
	
	var tileX = this.tileX;
	var tileY = this.tileY;
	
	var newdepth = tileY + tileX * tileHeightHalf + 65;
	var olddepth = this.depth;
	

		if (newdepth !== olddepth) {
		this.depth = newdepth;
		}

	
	var motion = this.motion;
	var direction = this.direction;
	
	//console.log('Motion: '+motion+' Direction: '+direction);
	//console.log('X:'+tileX+' Y:'+tileY);
	
	if (motion === "walk") {
		var walkDirection = this.motion + this.direction;
		this.play(walkDirection);
	}

	if (motion === "attack") {
		var attackDirection = this.motion + this.direction;
		this.play(attackDirection);
	}

	if (motion === "idle") {
		var idleDirection = this.motion + this.direction;
		this.play(idleDirection);
	};		
}

}

create () {

		tileGroup = this.add.group();
	
	dontWalk = this.add.group();
	
	ground = this.matter.world.nextCategory();
	groundunits = this.matter.world.nextCategory();

 spawnTiles();

//HOW THE UNIT IS GENERATED, (FOR CONTEXT OF THE PROBLEM)
	Units[unitId] = this.add.existing(new Metrus(this, centerX + txOffset, centerY + tyOffset, unitAction, unitDirection, 150, unitId, i, j));		

//ATTACK BUTTON IS CLICKED
	attack.on('pointerdown', function(){
		
		if (attackState == true) {
			//ALREADY SELECTED
			this.clearTint();
			attackState = false
			
		}else{
			//NOT YET SELECTED
			attackState = true;	
			this.tint = 0xFF0000;
			
		}
	});
			
			//ATTACK TARGET IS CLICKED
			this.input.setHitArea(tileGroup.getChildren()).on('gameobjectdown', function(pointer, gameObject, scene) {
		
			if (attackReady == true) {
			var attackX = pointer.worldX;
			var attackY = pointer.worldY;
			var gameTileX = gameObject.x;
			var gameTileY = gameObject.y;
			gameObject.priorityID=0;

			attackSprite.x = attackX; 
			attackSprite.y = attackY;
			attackSprite.alpha = 1;
			attackSprite.play('attackanim');
				
			setTimeout(function(){
			attackSprite.alpha = 0;
			}, 200); 
				

				
			for (var i = 0; i < selectedArray.length; i++)
			{	
				const thisUnit = Units[selectedArray[i]];
				
				thisUnit.targetX = attackX;
				thisUnit.targetY = attackY;

                var theScene = this.scene;
                var speed = thisUnit.speed;


                var distance = Phaser.Math.Distance.BetweenPoints(thisUnit, gameObject);
                thisUnit.motion = "walk";
				
		theScene.tweens.add({
									targets: thisUnit,
									x: attackX,
									y: attackY,
									duration: distance/speed
								});		

						}

			attackReady = false;
			attackState = false; 

			}
				
		});
			
}

update () {

		//UPDATE DEPTH SORTING IF MOVING
	for (let q in Units) {
		if (Units[q].motion == "walk") {
			var tileX = Units[q].tileX;
			var tileY = Units[q].tileY;
			Units[q].update();
		}
	}

}

spawnTiles () {
//LOOPS THROUGH levelData (LOOPING OMITTED), TILES MADE THIS WAY:
				//DEFINE TILE TYPES
			
			//GRASS0
			if (tileType==0)
			{
			thisTile = this.matter.add.sprite(centerX + tx, centerY + ty, 'flatsprite',0, { shape: { type: 'fromVerts', verts: iso, flagInternal: true } }).setStatic(true);
			thisTile.depth = centerY + ty;
			thisTile.tileX = i;
			thisTile.tileY = j;
			tileGroup.add(thisTile);
			}


			//WATER
			if (tileType==9)
			{
			
            thisTile = this.matter.add.sprite(centerX + tx, centerY + ty, 'flatsprite',5, { shape: { type: 'fromVerts', verts: iso, flagInternal: true } }).setStatic(true);	
			thisTile.depth = centerY + ty;
			thisTile.tileX = i;
			thisTile.tileY = j;
			dontWalk.add(thisTile);
			thisTile.setInteractive();
			thisTile.setCollisionCategory(ground);
			thisTile.setCollidesWith([groundunits]);
			}	


}

(I have obviously omitted a fair amount of code for easy readability)

Problem 1: when the unit moves, the update for depth sorting causes the sprite to flicker, as if its being updated constantly but never finishes.

Problem 2: my units don’t collide properly with my collision tiles, they sort of jump through them

I have attached a video to this post to demonstrate, and the live demo is at:
http://astralforge.net

2021-05-23 23-35-22.mkv (3.2 MB)

Thanks!

I see no depth sorting. Look up z-fighting.

So my tile depth is declared with this:

thisTile = this.matter.add.sprite(centerX + tx, centerY + ty, 'flatsprite',0, { shape: { type: 'fromVerts', verts: iso, flagInternal: true } }).setStatic(true);
thisTile.depth = centerY + ty;

and then my unit depth is set using my Metrus constructor with:

this.depth = (tileY + tileX) * tileHeightHalf + 65;

then I suspect it is this script in update causing the z-fighting:

		//UPDATE DEPTH SORTING IF MOVING
for (let q in Units) {
	if (Units[q].motion == "walk") {
		var tileX = Units[q].tileX;
		var tileY = Units[q].tileY;
		Units[q].update();
	}
}

which updates the unit with the Metrus constructor’s update() like so:

	var tileX = this.tileX;
var tileY = this.tileY;

var newdepth = tileY + tileX * tileHeightHalf + 65;
var olddepth = this.depth;


	if (newdepth !== olddepth) {
	this.depth = newdepth;
	}

Is there something I could change with any of these to prevent the z-fighting? Arent these a pseudo-way of depth sorting? My Issue is that I do not want to limit my units to strict movement within tiles, I want them to freely roam through each tile’s height and width, so conventional depth sorting with movement (ie: character moves exactly one Y tile, update depth by one Y) won’t work for what I need.

Read this and this.

This is not easy. My advice: go with enable3d.