Is it possible to delete a certain collision's mask? (SOLVED)

For example I have Mask1, Mask2, Mask3
is it possible to delete mask2?
all I have found in docs is

msg.post("#collisionobject", "disable")

Or you can remove a mask with msg?

Im sorry that I forget to set the thread in the questions section

No, you cannot alter the masks but you can easily tell an object to ignore collision by sending it a message to set a state:

function on_message(self, message_id, message, sender)
  if message_id == hash("ignore_collision") then
    self.ignore_collision = true
  elseif message_id == hash("collision_response") and not self.ignore_collision then
    -- do stuff on collision
  end
end
3 Likes

I have tried this

msg.post("/level/controller#platform_factory", "ignore_collision")

tried “/level/objects/platform#go” but didnt really work

here is the script that is part of the go

function on_message(self, message_id, message, sender)
	if message_id == hash("ignore_collision") then
		print("got it")
		msg.post("#collisionobject", "disable")
	end
end

it doesn’t print anything or work

It looks like you’re posting this message to a factory component (platform_factory). Is that intended? Or is platform_factory a script? You should be posting it to a script that can then do a msg.post() to the collision object.

Oh I thought that I should send the message to the go(game object) my bad but even if Im posting to the platform script it can’t find the instance of the script
I changed to "/level/objects/platform#script(I’m using the runner example from the learning section) I feel like I’m using the msg.post really wrong

In trying basically to make the game object in the factory will ignore it’s collision when I press the button(from the runner example)

Ok, so you want to disable collisions for some spawned game objects? And the game objects have collision objects? Do you want to disable collisions for already spawned platforms or only for new platforms?

No matter what you want to do you need to understand the basics of message passing and how to disable components (regardless if they are collision objects, sprites, spine models or something else).

Disabling components
You disable a component by posting a disable message to the component. Like this:

msg.post("foo#bar", "disable")

This will disable the component with id bar on the game object with id foo. That’s it. There is nothing more to it. And you enable a component by posting an enable message. You can also disable all components on a game object by posting the message to the game object without specifying a component:

msg.post("foo", "disable")

Now that we are armed with the knowledge of how to disable game objects we need to learn a bit about how factories work.

Factories and game object ids
The above example of disabling components on a game object with a predefined id such as foo is easy to understand. But what about collection factories? When you create a game object using a factory the game object will be given a generated id:

local id = factory.create("#myfactory")
print(id)  -- hash("/instance0")

The id will be auto generated and incremented to ensure that all ids are unique. Sometimes ids can also be reused if you delete generated game objects, but in general this is the way ids are assigned to factory created game objects. We can still post messages to generated game objects:

local id = factory.create("#myfactory")
msg.post(id, "disable")

This would post a disable message to the newly spawned game object. But what if we want to disable a component on the game object and not all components? We can create a URL to the component like this:

local id = factory.create("#myfactory")
msg.post(msg.url(nil, id, "bar"), "disable")

This would disable the component bar on the spawned game object.

Solving your problem
You have a couple of different options. You could post a message to the controller.script that is responsible for spawning platforms and let that script keep track of if collisions should be ignored or not. If collisions should be ignored the controller.script could post a message to the generated platform to disable the collision component.

Another option would be that the you post a message to the hero.script and let the hero keep track of if it should react to collisions with platforms or not. In this case you’d probably just keep a boolean flag to track if it should ignore platform collisions or not and then maybe have a separate collision group for ground and one for platforms (I think both have the group geometry in the tutorial).

4 Likes

Sorry if I caused confusion here. It is, of course, much easier to just send “disable” to the collisionobject component and then send “enable” when you want it to register collisions again.

1 Like

So I’m trying the second way(not exactly) so when I send a message to the controller I’m telling it this
msg.post(msg.url(nil, p, “danger_edges”), “disable”)
I converted the p variable(the one that creates the factory) from local to global but the platforms freak out

Yeah, if you spawn several game objects and assign each one’s id to the same global variable it will be overwritten at each spawn.

So what should I do? Write another function that get the ids and run it in the on message function? There is no easier way to do that?

If you want to disable collision on all spawned objects you can store the ids and then iterate over them.

Spawn objects and store the ids:

function init(self)
  self.spawn_ids = {}
end

...
  local id = factory.create(...)
  table.insert(self.spawn_ids, id)
...

and then when you want to disable all spawned objects’ collision objects:

for i, id in ipairs(self.spawned_ids) do
  msg.post(msg.url(nil, id, "collisionobject"), "disable")
end
4 Likes