Actor.Touch() fires twice per tick on Y axis, once on X

Bugs that have been investigated and resolved somehow.

Moderator: GZDoom Developers

Forum rules
Please don't bump threads here if you have a problem - it will often be forgotten about if you do. Instead, make a new thread here.
User avatar
Sir Robin
Posts: 537
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

Actor.Touch() fires twice per tick on Y axis, once on X

Post by Sir Robin »

Summon this and approach it:

Code: Select all

Class TouchTest : Actor
{
	override void Touch (Actor toucher)
	{
		console.printf('Touched '..level.MapTime);
	}
	Default
	{
		Height 64;
		Radius 32;
		+SOLID
		+SPECIAL
	}
	States{
		Spawn:
			PLAY A -1;
			Stop;
	}
}
the Touch() function is called twice per tic if touched from north or south, once per tic if touched from east or west
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
Posts: 49184
Joined: Sat Jul 19, 2003 10:19 am
Location: Germany

Re: Actor.Touch() fires twice per tick on Y axis, once on X

Post by Graf Zahl »

It is not about axis but movement speed. If the moving actor is too fast it splits its move into smaller parts - and each move can cause a touch event. Unfortunately this behavior is so deeply ingrained into Doom mapping that it simply cannot be fixed.
User avatar
Sir Robin
Posts: 537
Joined: Wed Dec 22, 2021 7:02 pm
Graphics Processor: Intel (Modern GZDoom)
Location: Medellin, Colombia

Re: Actor.Touch() fires twice per tick on Y axis, once on X

Post by Sir Robin »

I'm still seeing this behavior. My work around is to keep a list of actors who touched the actor each tic and only let them do it once per tic.

Code: Select all

class Trigger_BumpOrUse : Actor
{
	array<actor> touchers;
	
	default
	{
		height 64;
		radius 32;
		+Solid
		+NOGRAVITY;
		+Special;
	}
	
	override void tick()
	{
		super.tick();
		touchers.clear();
	}
	
	override void Touch(Actor toucher)
	{
		//Don't let an actor touch more than once per tic
		if (touchers.find(toucher) != touchers.size()) return;
		
		//record this toucher for this tic
		touchers.push(toucher);
		
		console.printf(GetCharacterName().."@"..level.time..": Touched by "..(toucher? toucher.GetCharacterName() : "[NULL]"));//DEBUG
		Trigger(toucher);
	}
	
	override bool Used(Actor user)
	{
		console.printf(GetCharacterName().."@"..level.time..": Used by "..(user ? user.GetCharacterName() : "[NULL]"));//DEBUG
		Trigger(user);
		return true;
	}
	
	virtual void Trigger(actor tripper)
	{
		console.printf(GetCharacterName().."@"..level.time..": Triggered by "..(tripper ? tripper.GetCharacterName() : "[NULL]"));//DEBUG
		tripper.A_CallSpecial(special, args[0], args[1], args[2], args[3], args[4]);
	}
}

Return to “Closed Bugs [GZDoom]”