Jump to content

Andy90

Members
  • Posts

    190
  • Joined

  • Last visited

Posts posted by Andy90

  1. I've developed a second iteration of the script, this time utilizing a prefab. This means there are now two scripts in play: the Spawn Manager and the tree itself. 


    1. Spawn Manager

    Script.terrain = nil
    Script.player = nil --Entity "Player"
    Script.playerDistance = 30 --Float "Player Distance"
    Script.seed = 123456 --Float "Seed"
    Script.treeCount = 25 --Int "Trees"
    Script.minDist = 25 --Float "Min Distance"
    Script.maxDist = 75 --Float "Max Distance"
    Script.tree = "" --Path "Model"
    Script.treeMinHeight = 0.5 --Float "Min height"
    Script.treeMaxHeight = 1.0 --Float "Max height"
    Script.aabbCheck = false --Bool "AABB Check"
    Script.debug = true --Bool "Debug Mode"
    Script.treeData = {}
    
    function Script:Start()
    	self.entity:Hide()
    	--Find the terrain
    	local world = World:GetCurrent()
    	for i = 0, world:CountEntities() - 1 do
    		local entity = world:GetEntity(i)
    		if entity:GetClass() == Object.TerrainClass then
    			self.terrain = tolua.cast(entity, "Terrain")
    		end
    	end
    
    	local treeData = {}
    
    	--Creates the tree data for the pivot tree
    	local x = self.entity:GetPosition(true).x
    	local z = self.entity:GetPosition(true).z
    	local y = self.terrain:GetElevation(x, z)
    	local treeInfo = {
    		TreeName = self.entity:GetKeyValue("name") .. "_tree_center",
    		TreeX = x,
    		TreeY = y,
    		TreeZ = z,
    		TreeScale = 1.0,
    		Visible = true,
    		HideTime = 0
    	}
    	table.insert(treeData, treeInfo)
    
    	--Place a sphere at the pivot location
    	if self.debug then
    		local spehre = Model:Sphere()
    		spehre:SetColor(1.0, 0.0, 0.0)
    		spehre:SetScale(1.0)
    		spehre:SetPosition(x, y, z)
    	end
    
    	math.randomseed(self.seed)
    	for i = 0, self.treeCount do
    		--Calculate the angle and the distance for the new tree
    		local deg = 360 / self.treeCount * i
    		local radians = math.rad(deg)
    		local distance = math.random(self.minDist, self.maxDist)
    		local sin = math.sin(radians)
    		local cos = math.cos(radians)
    
    		--Calculate the x,y,z cords for the tree
    		local x = self.entity:GetPosition(true).x + distance * cos
    		local z = self.entity:GetPosition(true).z + distance * sin
    		local y = self.terrain:GetElevation(x, z)
    
    		--Calculates the scale for the tree
    		local scale = math.random(self.treeMinHeight * 100, self.treeMaxHeight * 100) / 100
    
    		--If AABB Check is enabled check for collision
    		if self.aabbCheck then
    
    			for _,item in pairs(self.treeData) do
    				if Vec3(item.TreeX, item.TreeY, item.TreeZ):DistanceToPoint(Vec3(x,y,z)) < 0.5 then
    					System:Print("Double Point")
    					goto continue
    				end
    			end
    
    			for i = 0, world:CountEntities() - 1 do
    				local entity = world:GetEntity(i)
    				if entity:GetClass() == Object.ModelClass and entity:GetParent() == nil then
    					if entity:GetAABB():IntersectsPoint(Vec3(x,y,z), 1) then
    						System:Print("intersect with entity " .. entity:GetKeyValue("name"))
    						goto continue
    					end
    				end
    			end
    		end
    
    		--Adds the tree info into the table
    		local treeInfo = {
    			TreeName = self.entity:GetKeyValue("name") .. "_tree_" .. i,
    			TreeX = x,
    			TreeY = y,
    			TreeZ = z,
    			TreeScale = scale,
    			Visible = true,
    			HideTime = 0
    		}
    		table.insert(treeData, treeInfo)
    		::continue::
    	end
    	self.treeData = treeData;
    end
    
    function Script:UpdateWorld()
    	--Enables the trees when the player is nearby
    	local distance = self.entity:GetDistance(self.player)
    	if distance > self.playerDistance + self.maxDist and not self.entity:Hidden() then
    		self.entity:Hide()
    		self:HideTrees()
    	elseif distance < self.playerDistance + self.maxDist and self.entity:Hidden() then
    		self.entity:Show()
    		self:ShowTrees()
    	end
    	-- System:Print(self.entity:GetKeyValue("name") .. " Children " .. self.entity:CountChildren() .. " / " .. #self.treeData)
    end
    
    function Script:ShowTrees()
    	System:Print("Show Trees!")
    	for _, item in pairs(self.treeData) do
    		local tree = Prefab:Load(self.tree)
    		tree.script.treeData = item
    		tree:SetPosition(item.TreeX, item.TreeY, item.TreeZ)
    		tree:SetScale(item.TreeScale)
    		tree:SetKeyValue("name", item.TreeName)
    		tree:SetParent(self.entity)
    		if not item.Visible then
    			tree:Hide()
    		end
    	end
    end
    
    function Script:HideTrees() 
    	local t = self.entity:CountChildren()
    	for i = 0, self.entity:CountChildren() -1 do
    		local child = self.entity:GetChild(i)
    		child:Release()
    	end
    end

    2. Tree Script

    Script.treeData = nil
    Script.respawn = 10 * 60000
    
    function Script:UpdateWorld()
    	if self.entity:Hidden() then
    		local now = Time:GetCurrent()
    		if now > self.treeData.HideTime + self.respawn then
    			self.treeData.Visible = true
    			self.entity:Show()
    		end
    	end
    end
    
    function Script:Collision(entity, position, normal, speed)
    	if entity:GetKeyValue("name") == "player" then
    		if Window:GetCurrent():KeyDown(Key.E) then
    			self.entity:Hide()
    			self.treeData.Visible = false
    			self.treeData.HideTime = Time:GetCurrent()
    		end
    	end
    end

    As you can see, the trees are no longer created within the Start function. They are dynamically generated when the player is nearby and released when the player moves away. This enhancement greatly improves performance. For example, if you have 10 spawners each with 50 trees, the old script would add 500 entities to the scene. With the new script, you only add the 10 pivot points, and create the entities for the trees only when the player is nearby.

    I hope this will help anyone within the future :) 

    • Upvote 1
  2. Ah okey this sounds very nice. I finished my script for a tree spawning based on a pivot
     

    Script.terrain = nil
    Script.player = nil --Entity "Player"
    Script.playerDistance = 30 --Float "Player Distance"
    Script.seed = 123456 --Float "Seed"
    Script.treeCount = 25 --Int "Trees"
    Script.minDist = 25 --Float "Min Distance"
    Script.maxDist = 75 --Float "Max Distance"
    Script.tree = "" --Path "Model"
    Script.treeMinHeight = 0.5 --Float "Min height"
    Script.treeMaxHeight = 1.0 --Float "Max height"
    Script.debug = true --Bool "Debug Mode"
    
    function Script:Start()
    	--Find the terrain
    	local world = World:GetCurrent()
    	for i = 0, world:CountEntities() - 1 do
    		local entity = world:GetEntity(i)
    		if entity:GetClass() == Object.TerrainClass then
    			self.terrain = tolua.cast(entity, "Terrain")
    		end
    	end
    
    	--Sets a tree at the pivot location
    	local x = self.entity:GetPosition(true).x
    	local z = self.entity:GetPosition(true).z
    	local y = self.terrain:GetElevation(x, z)
    	local tree = Model:Load(self.tree)
    	tree:SetPosition(x, y, z)
    	tree:SetParent(self.entity)
    
    	--Place a sphere at the pivot location
    	if self.debug then
    		local spehre = Model:Sphere()
    		spehre:SetColor(1.0, 0.0, 0.0)
    		spehre:SetScale(1.0)
    		spehre:SetPosition(x, y, z)
    	end
    
    	math.randomseed(self.seed)
    	for i = 0, self.treeCount do
    		--Calculate the angle and the distance for the new tree
    		local deg = 360 / self.treeCount * i
    		local radians = math.rad(deg)
    		local distance = math.random(self.minDist, self.maxDist)
    		local sin = math.sin(radians)
    		local cos = math.cos(radians)
    
    		--Calculate the x,y,z cords for the tree
    		local x = self.entity:GetPosition(true).x + distance * cos
    		local z = self.entity:GetPosition(true).z + distance * sin
    		local y = self.terrain:GetElevation(x, z)
    
    		--Calculates the scale for the tree
    		local scale = math.random(self.treeMinHeight * 100, self.treeMaxHeight * 100) / 100
    
    		--Creates the tree within the scene
    		local tree = Model:Load(self.tree)
    		tree:SetPosition(x, y, z)
    		tree:SetScale(scale)
    		tree:SetParent(self.entity)
    
    		--Creates a debug sphere at the tree location
    		if self.debug then
    			local spehre = Model:Sphere()
    			spehre:SetColor(1.0, 1.0, 0.0)
    			spehre:SetScale(1.0)
    			spehre:SetPosition(x, y, z)
    		end
    	end
    end
    
    function Script:UpdateWorld()
    	--Enables the trees when the player is nearby
    	local distance = self.entity:GetDistance(self.player)
    	if distance > self.playerDistance then
    		self.entity:Hide()
    	else
    		self.entity:Show()
    	end
    end

     

    • Like 1
  3. Ah, okay. Thanks anyway. I'll give it a shot with C++. If that doesn't work, I'll have to explore alternative methods to add wood to the player's inventory. Perhaps by incorporating additional prefab trees placed around a pivot, similar to the suggestion by @Alienhead.

    ----

    1 hour ago, Josh said:

    In Ultra this is quite a lot more flexible.

    For example, will it be possible to access individual vegetation objects in the Ultra Engine?

     

     

  4. The new dev diary is online :) i also found a name for the project "Nuclear Frontiers" i think the name fits well. Here is the logo for it



    Logo.png.e603f1889079f108a89e794a47e60637.png

     

    an you can watch the new dev diary here: 

     

    • Like 3
  5. Thanks for the anwesers. 

    On 10/3/2023 at 2:59 AM, Alienhead said:

    Check out AABB.

    i will check this :)

     

     

    On 10/3/2023 at 3:17 AM, reepblue said:

    If it's physics related, use the Collision function instead of UpdatePhysics Use the entity argument to filter what entity or type it needs to trigger your event.

    yeah i set a boolean variable to true within the method and set it to false within UpdatePhysics. So at the moment its working fine. 

  6. 5 hours ago, Josh said:

    Picking does not work on animated models because the vertices only move around on the GPU. In my AI scripts I handled this by using the box pick mode on all children of the model, then disabling picking on the model itself:

    Thank you, this is very helpful. I believe I've properly configured the parameters in my pick function to acquire the closest target. However, there's a chance I may have misunderstood something.

    self.cam:Pick(p.x, p.y, pickinfo, pickradius, true, Collision.Prop)

    -----

    I also edited the model a bit because at some parts of the body was no hit registration. So i added some spheres and asign them an invisible hitbox material. Works great so far 

    image.thumb.png.adf9112f1061646fa13f08fff48ddcc9.png

  7.  

    Hello :),

    I believe that incorporating widgets and plugins for the new engine would be a fantastic addition. This would enable users to customize and enhance their workflow with personalized "features" and also allow for easy sharing within the community.

    For instance, if you wish to generate random elements within a scene, you could design a custom widget for the right tab bar. This widget could be programmed to create these elements and seamlessly integrate them into the active scene. Another example could be the implementation of a "road" tool designed to efficiently construct roads.

     

  8. Hello :)

    I would like to inquire if it's possible to use an Lua function to determine if one entity collides with another. My objective is to verify whether the player remains within a trigger area. At present, I accomplish this by setting a boolean variable to true in the event of a collision with the player using Script:Collision. Then, in Script:UpdatePhysics(), I repeatedly reset this variable to false.

  9. Here is my effect manager script. It's really simple to use. Just create a pivot in your map and add the script. Then assign your camera to the script.

    Script.effects = {}
    Script.camera = nil --Entity "Camera";
    
    function Script:Start()
    	self:AddEffect("bloom", "Shaders/PostEffects/bloom.lua", true)
    	self:AddEffect("ssao", "Shaders/PostEffects/ssao.shader", true)
    	self:AddEffect("godrays", "Shaders/PostEffects/godrays.lua", true)
    	self:AddEffect("grayscale", "Shaders/PostEffects/grayscale.shader", false)
    	self:BuildEffectChain()
    end
    
    --Adds a new effect to the effect chain
    function Script:AddEffect(name, file, enabled)
    	local effect = {
    		name = name,
    		file = file,
    		enabled = enabled
    	}
    	table.insert(self.effects, effect)
    	if enabled then
    		self:BuildEffectChain()
    	end
    	return #self.effects + 1
    end
    
    --Disables the effect at position n
    function Script:DisableEffect(index)
    	if self.effects[index].enabled == true then
    		self.effects[index].enabled = false
    		self:BuildEffectChain()
    	end
    end
    
    --Enables the effect at position n
    function Script:EnableEffect(index)
    	if self.effects[index].enabled == false then
    		self.effects[index].enabled = true
    		self:BuildEffectChain()
    	end
    end
    
    --Returns the effect index with the given name
    function Script:GetEffectIndex(name)
    	for i, item in ipairs(self.effects) do
    		if item.name == name then
    			return i
    		end
    	end
    end
    
    --Returns the effect with the given name (untested)
    function Script:GetEffect(name)
    	local effectIndex = self:GetEffectIndex(name);
    	return self.effects[effectIndex];
    end
    
    -- Rebuils the effect chain
    function Script:BuildEffectChain()
    	self.camera:ClearPostEffects()
    	for i, item in ipairs(self.effects) do
    		if item.enabled then
    			self.camera:AddPostEffect(item.file)
    		end
    	end
    end

    You can call the functions from the script when you assign the pivot as the entity. For example:

    image.png.12071d884b0c375e6d17565849deb312.png

    and use

    local effectIndex = self.effectManager.script:GetEffectIndex("grayscale");
    self.effectManager.script:DisableEffect(effectIndex);
    • Like 3
  10. Hello :) the camera pick is working realy wired for me. You can see it within the video 2023-09-30 02-36-14 (streamable.com). This is my code

     

    function Script:Shot()
    	--Create a sphere to indicate where the pick hits
    	local pickradius = 0.1;
    
    	picksphere = Model:Sphere()
    	picksphere:SetColor(1.0, 0.0, 0.0)
    	picksphere:SetPickMode(0)
    	picksphere:SetScale(pickradius * 2.0)
    	picksphere:Hide()
    
    	picksphere:Hide()
    	local pickinfo = PickInfo()
    	local p = window:GetMousePosition()
    	if (self.cam:Pick(p.x, p.y, pickinfo, pickradius, true, Collision.Prop)) then
    		picksphere:Show();
    		picksphere:SetPosition(pickinfo.position);
    		local name = pickinfo.entity:GetKeyValue("name");
    		pickinfo.entity:Hide();
    		System:Print(name);
    	end
    end

     

×
×
  • Create New...