While trying to set parent transform position gets changed

I’m trying to make apple object child of cupboard rack when apple is placed/drop on rack. But while apple object is dragging on rack collsion object it’s flickering and when dragging out of rack apple object position gets changed.

parent-child

I’m setting and removing parent of apple object when trigger responce is happeing while entering over rack collision object.

apple object script -

local cursor = require "in.cursor"

local gravity = -20

function init(self)
	self.velocity = vmath.vector3()
	self.ground_contact = false
	self.landed = false
	self.not_dragging = true
	self.rack_contact = false

	self.has_inside = false
	self.keep_still = false
	self.container = hash('/food')
end

function final(self)
	-- Add finalization code here
	-- Learn more: https://defold.com/manuals/script/
	-- Remove this function if not needed
end

function update(self, dt)
	-- local gravity = vmath.vector3(0, gravity, 0)
	local position = go.get_position()
	-- self.velocity.y = self.velocity.y + gravity

	-- are we in contact with a rack or land?
	if self.has_inside or self.landed then
		-- set vertical velocity if we are climbing up or down
		-- also set flag to indicate that we are climbing
		self.on_rack = true
		self.velocity.y = 0
	else
		self.on_rack = false
	end

	-- apply gravity if there's no ground contact and if it's not sitting on rack
	if not self.ground_contact and not self.on_rack and not self.keep_still then
		-- self.velocity.x = 200
		self.velocity.y = self.velocity.y + gravity
	end

	-- if not self.landed and self.not_dragging then
	-- 	-- apply velocity to the player character
	-- 	go.set_position(go.get_position() + self.velocity * dt)
	-- end
	
	go.set_position(go.get_position() + self.velocity * dt)

	self.correction = vmath.vector3()
	self.ground_contact = false
	-- self.has_inside = false
end

-- from the platformer tutorial on defold.com
local function handle_geometry_contact(self, normal, distance)
	local proj = vmath.dot(self.correction, normal)
	local comp = (distance - proj) * normal
	self.correction = self.correction + comp
	go.set_position(go.get_position() + comp)
	if normal.y > 0.7 then
		self.ground_contact = true
	end
	proj = vmath.dot(self.velocity, normal)
	if proj < 0 then
		-- remove that component in that case
		self.velocity = self.velocity - proj * normal
		self.velocity.x = 0
	end
end

function on_message(self, message_id, message, sender)
	if message_id == hash("contact_point_response") then
		if message.group == hash("land") or message.group == hash("rack") then
			handle_geometry_contact(self, message.normal, message.distance)
		end
	elseif message_id == hash("trigger_response") then
		if message.enter then
			if message.other_group == hash('land') or message.other_group == hash("rack") then
				print('inside land')
				msg.post('#collisionobject', "disable")
				self.landed = true
				if message.other_group == hash("rack") then
					print("inside rack")
					self.has_inside = true
					self.container = message.other_id
					msg.post(".", "set_parent", { parent_id = message.other_id, keep_world_transform = 1 })
					local position = go.get_position()
					position.z = 0.1
					go.set_position(position)
				end
			end
		else
			if message.other_group == hash('land') or message.other_group == hash("rack") then
				msg.post('#collisionobject', "enable")
				print('outside land')
				self.landed = false
				if message.other_group == hash("rack") then
					print("outside rack")
					self.has_inside = false
					self.container = hash("/food")
					msg.post(".", "set_parent", { keep_world_transform = 1 })
					local position = go.get_position()
					position.z = 0.5
					go.set_position(position)
				end
			end
		end
	elseif message_id == cursor.PRESSED then
		-- print("Pressed", message.id, message.group, message.x, message.y)
		-- msg.post('#collisionobject', "disable")
	elseif message_id == cursor.RELEASED then
		-- print("Released", message.id, message.group, message.x, message.y)
		-- msg.post('#collisionobject', "enable")
		self.not_dragging = true
	elseif message_id == cursor.DRAG then
		self.not_dragging = false
		-- if self.has_inside then
		-- 	msg.post(".", "set_parent", { parent_id = self.container, keep_world_transform = 1 })
		-- 	self.keep_still = true
		-- 	print("my parent id", go.get_parent())
		-- else
		-- 	msg.post(".", "set_parent", { keep_world_transform = 1 })
		-- 	self.keep_still = false
		-- end
	elseif message_id == hash("keep it inside") then
		self.keep_still = true
	elseif message_id == hash("keep it inside opened") then
		self.keep_still = false
	end
end

function on_input(self, action_id, action)
end

function on_reload(self)
	-- Add reload-handling code here
	-- Learn more: https://defold.com/manuals/hot-reload/
	-- Remove this function if not needed
end

You probably want to look into go.set_parent() and the argument " keep_world_transform which lets you keep the world transform of the child, and it will automatically calculate the correct transform relative the new parent.

5 Likes

image

function init(self)
	go.set_parent(go.get_id(),nil, true)
	print("parent id =", go.get_parent())
end

In the script I’m unparenting food game object from its parent some, then
printing parent of it so it has to print nil. But I’m getting here
image

And while trying to set parent to any game object and then printing parent of it getting nil always where it has to print parent id.

Are you getting this result because you are setting parent and printing in the same cycle? What if you check after the frame using a timer ?

timer.delay(0.01, false, function() print("parent id =", go.get_parent()) end)

1 Like