How do I keep the same x and z orientation when the y orientation is different?

Hi hi,

How would I go about keeping the same x and z orientation when the y orientation is something other than 0? It’s a little daunting and hard to elaborate on, but I’ll try my best.

I have a nice lively dynamic foliage system. Whenever a character travels through a patch of foliage, whether it’d be bushes, flowers or cattail plants, the foliage shakes as such:

As you can see, the foliage moves perfectly; out of the way of the character, and neatly. However once I orientate a foliage any amount, it still locks in the same x and z orientation:?

Each blue part is orientated 90 degrees:

And each red part is orientated 0 degrees:

I think this occurs due to my code taking in a unit vector (The humanoid’s MoveDirection) and then converting it into a CFrame via radians.

My current code looks like this:

-- @ .getFoliageDirection(x0, z0): Returns a new cframe rotation matrix based on the x0, and z0 arguments.
	-- x0 being the x move direction, and z0 likewise.
	local function getFoliageDirection(x0: number, z0: number)
		return CFrame.Angles(z0, 0, -x0)
	end
	
	local function updateFoliageCFrame(foliage: BasePart, moveDirection: Vector3)
		local x0 = math.rad(moveDirection.X * FOLIAGE_ROTATION_MULTIPLIER) -- FOLIAGE_ROTATION_MULTIPLIER = 45
		local z0 = math.rad(moveDirection.Z * FOLIAGE_ROTATION_MULTIPLIER)
		
		local originalCFrame = foliage:GetAttribute("OriginalCFrame") -- this is the foliage original cframe
		local foliageDirection = getFoliageDirection(x0, z0)
		
		tweenService:Create(foliage.PivotValue, FOLIAGE_BEGIN_TWEEN_INFO, { Value = originalCFrame * foliageDirection }):Play()
	end

I was thinking of applying a sort of directional modifier based on the orientation? For example, if the unit vector was 1, 0, 0, but the orientation was 45 degrees, it could somehow shift the direction of the unit vector?

Any help would be greatly appreciated. Thank you :slight_smile:

2 Likes

i think it’s because Humanoid.MoveDirection is object-relative and not world-relative

i had to reverse engineer some of your code but eventually got a similar effect working for myself using .touched and .touchended

local FOLIAGE_ROTATION_MULTIPLIER = 45

local ts = game:GetService("TweenService")

local function getFoliageDirection(x0: number, z0: number)
	return CFrame.Angles(math.rad(-z0 * FOLIAGE_ROTATION_MULTIPLIER), 0, math.rad(-x0 * FOLIAGE_ROTATION_MULTIPLIER))
end

local function updateFoliageCFrame(foliage: BasePart, moveDirection: Vector3)
	local originalCFrame = foliage:GetAttribute("OriginalCFrame") -- :SetAttribute("OriginalCFrame", p:GetPivot())
	local space = originalCFrame:VectorToObjectSpace(moveDirection)
	local foliageDirection = getFoliageDirection(space.X, space.Z)

	ts:Create(foliage, TweenInfo.new(0.5, Enum.EasingStyle.Back, Enum.EasingDirection.Out), { CFrame = originalCFrame:ToWorldSpace(foliageDirection) }):Play()
end
3 Likes

Thank you :pray:

Everything seems to be working perfectly. Additionally I tested it on a slope, that went really well.

I’m not sure why I didn’t think of using the ‘to-space’ functions sooner.

Appreciations, and self doubt aside :sweat_smile:, thank you again :slight_smile:

3 Likes

that looks really nice!!

happy to have helped

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.